Skip to main content
An OAuth app lets users in your workspace sign in to your app with their Plain account. Your app then calls the API as that user, with the permissions their role already has, and Plain records those actions as that user. To call the API as an integration rather than as a user, create a machine user instead.

Choose an OAuth app type

The OAuth app type determines how your app authenticates when it exchanges an authorization code for an access token. Pick the type before you create the app, because you can’t change it afterwards:
  • Client-side: your app exchanges the code in a browser or a mobile or desktop app, where a secret wouldn’t stay secret. The app has no client secret and must use Proof Key for Code Exchange (PKCE).
  • Server-side: your app exchanges the code from your backend, where you can keep a secret. Plain creates a client secret for the app and shows it once.
PKCE proves that the token request comes from the app that started the sign-in. Your app generates a random code verifier, sends its SHA-256 hash as the code challenge when the user signs in, then sends the verifier itself with the authorization code. To switch types, create a new OAuth app and move your integration to it.

Create an OAuth app

Creating an OAuth app gives you a client ID, which identifies your app to Plain and isn’t secret. A server-side app also gets a client secret.
1

Open the form

Go to Settings → OAuth applications and click Add OAuth app.
2

Fill in the form

The form has these fields:
  • App name: The name users see when they sign in.
  • Description: Optional.
  • OAuth app type: Client-side or Server-side. The form selects Client-side by default.
  • Redirect URLs: Where Plain sends a user after they sign in. Put each URL on its own line.
  • Allowed origins: Shown only for a client-side app. See Allowed origins for a client-side app.
Each redirect URL and allowed origin must use HTTPS, or HTTP on localhost.
3

Create the app

Click Create OAuth app. For a client-side app, Plain opens the app’s settings page, which shows the client ID.For a server-side app, Plain first shows the client ID and client secret. Click Done to open the app’s settings page.
Copy the client secret before you click Done. You can’t see it again. If you lose it, create a new server-side app.
The list in Settings → OAuth applications shows each app’s type, and so does the Credentials card on the app’s settings page.

Allowed origins for a client-side app

An allowed origin is a website that may call Plain’s sign-in endpoints, such as the token endpoint, from the browser. A client-side app needs at least one, because it exchanges the code from the browser, and the browser blocks the call from any other origin. Write each origin on its own line as a scheme and host, with an optional port and no path, such as https://app.example.com or http://localhost:3000. A server-side app exchanges the code from your backend, so the create form doesn’t ask for allowed origins.

Get an access token

Your app gets an access token with the OAuth 2.0 authorization code flow: it sends the user to sign in, receives a code at a redirect URL, and exchanges that code for tokens. The authorization server is https://signin.auth.plain.com, and its OpenID configuration lists the endpoints.
1

Send the user to sign in

Redirect the user to the authorize endpoint with these query parameters:
  • client_id: Your app’s client ID.
  • redirect_uri: One of the app’s redirect URLs.
  • response_type: code.
  • scope: openid, plus offline_access if you want a refresh token.
  • state and nonce: Random values you generate for this sign-in. Check that the state Plain returns matches the one you sent.
  • code_challenge and code_challenge_method: The PKCE code challenge, with method S256. A client-side app must send these. A server-side app can skip PKCE, but we recommend it.
This builds the URL in TypeScript:
A user in more than one workspace chooses which workspace to sign in to. The app only works in the workspace you created it in.
2

Exchange the code for tokens

After the user signs in, Plain redirects to redirect_uri with a code. Exchange it at the token endpoint, https://signin.auth.plain.com/oauth2/token.For a server-side app, send the client secret from your backend. This request also sends the code verifier, because it used PKCE:
For a client-side app, send the code verifier and no client secret. The page’s origin must be one of the app’s allowed origins:
The response includes these fields:
  • access_token: The token you send to the API.
  • expires_in: How many seconds the access token lasts.
  • refresh_token: Included when the sign-in requested offline_access.
3

Refresh the access token

Before the access token expires, send the refresh token to the token endpoint with grant_type=refresh_token and the client ID. A server-side app also sends its client secret:
Store the refresh token from each response and use it for the next refresh.

Call the API

The API URL and request body are the same as for an API key; see Key details. Send the access token in the same header an API key uses:
Each query and mutation runs as the signed-in user, with their current role. Changing their role changes what the app can do, and removing them from the workspace stops the app working for them. If they lack a permission, the error names it. GraphQL subscriptions don’t accept OAuth app tokens. The API rejects a token from a disabled or deleted app, or from another workspace, with HTTP status 401 and the error code UNAUTHENTICATED. The error doesn’t say which of these applies.

Disable or delete an OAuth app

Disabling an OAuth app stops it without losing its settings. On the app’s settings page, turn off Enabled in the Status card and click Save changes. Users can’t sign in to the app, and the API rejects every request from it, including tokens issued before you disabled it, until you enable it again. To delete the app, use the Delete card on its settings page.
Deleting an OAuth app ends its access immediately. You can’t undo a delete.