Authentication

We use OAuth for partners wanting to develop integrations with Pleo to access Pleo data on behalf of customer, specifically the Authorization Code grant type. As we have taken a fairly standard approach, you can find further documentation here.

Cheatsheet

ParameterValue
Authorization Endpointhttps://auth.pleo.io/oauth/authorize —or—
https://auth.staging.pleo.io/oauth/authorize
Token Endpointhttps://auth.pleo.io/oauth/token —or—
https://auth.staging.pleo.io/oauth/token
Grant TypeAuthorization Code (with PKCE)
Client Credentialsclient_id and client_secret that you received after completing the client registration.
Redirect URIMust match exactly with the redirect_uri that you supplied during client registration.
ScopeFor testing, test:test and any similar value will work.
PKCERequired, S256 only. Verifier must conform to the RFC (43–128 characters, only alphanumeric characters and -\_.~)
Client AuthenticationAuthorization: Basic BASE64({client_id}:{client_secret})

Getting started

In order to begin building your OAuth solution, you will need be provided client credentials. You can request this completing the form here.

Client credentials for the staging environment will be provided within 1-3 business days via a secure channel.

Initiating the Authorization Request

The first step in the flow is obtaining an authorization code. The flow will need to be initiated from your application in a browser.

https://auth.pleo.io/oauth/authorize?
  client_id=<client_id>&
  redirect_uri=<redirect_uri>&
  scope=<scopes>&
  response_type=code&
  state=<state>&
  code_challenge_method=S256&
  code_challenge=<code_challenge>
  • <client_id>: provided to you during app creation
  • <redirect_uri>: must match the value you provided during app creation
  • <scope>: the list of scopes you have access to will be determined during the app creation process. Multiple scopes can be passed as a space-separated list, for example: scope=export:read export:write
  • <response_type>: always code
  • <state>: a string value. Should be request-specific. Will be returned back by the server on future requests. This is optional.
  • code_challenge_method: must be S256
  • code_challenge: must be a base64uri encoded sha256 hash of a code_verifier, a secret random string, that the client will need to present later during authorization code exchange. You MUST NOT expose code_verifier during authorization request.

The user will then be prompted to login:

Untitled

After which the user will be redirected by to the url specified in the original request containing the following in the query params:

  • code: the authorization which will be used to to obtain access and refresh tokens
  • state: this should match what was passed in the initial request

Getting Tokens

The authorization code obtained above is a temporary code that can be exchanged for an access and refresh token with the following request:

POST https://auth.pleo.io/oauth/token

grant_type=authorization_code&
redirect_uri=${REDIRECT_URI}&
code=${THE_CODE_FROM_ABOVE}&
code_verifier=${SOME_STRING}
  • Client authentication is performed using Authorization: Basic BASE64({client_id}:{client_secret}) header
  • redirect_uri must be the same as the one used to generate the authorization code
  • code_verifier from the initial request must included to verify you application originally sent the request

A successful response will look like:

{
  "access_token": "THE_ACCESS_TOKEN",
  "token_type": "Bearer",
  "expires_in": ACCESS_TOKEN_LIFETIME, // 10 mins.
  "refresh_token": "REFRESH_TOKEN", // optional
  "scope": "scope1 scope2"
}

Store the access_token and refresh_token securely.

The expires_in field describes the lifetime of the access token, in seconds since the moment it has been issued. After specified time, it will no longer be accepted by the resource servers, and a new access token should be obtained by making a request to the token endpoint. Your application can do this by making a request to a token endpoint using the refresh token grant, as described in the next section.

A response may not contain a refresh token. In this case, after the access token expires, the only way to obtain a new access token is to go through the authorization process again.

Refresh Tokens

Once you have a refresh token, this can be used to continue obtain new short-lived access tokens:

POST https://auth.pleo.io/oauth/token

grant_type=refresh_token&
refresh_token=xxxxxxxxxxx

You must present your client_id and client_secret using Basic HTTP authentication.

As successful response will include a new access_token and a new refresh_token, which you will need to stored in replacement of the previously used refresh token:

{
  "access_token": "THE_ACCESS_TOKEN",
  "token_type": "Bearer",
  "expires_in": ACCESS_TOKEN_MILLI_LIFETIME, // 10 mins.
  "refresh_token": "REFRESH_TOKEN",
  "scope": "scope1+scope2..."
}

Token Introspection

The token introspection endpoint to return information about a token. Client authentication is performed using Authorization: Basic BASE64({client_id}:{client_secret}) header. Note that clients can only introspect tokens generated with their own client.

POST https://auth.pleo.io/oauth/token/introspect

{
    "token": "{token}"
}

A successful request will return the following response

{
	"active": true,
	"sub": "RESOURCE_ID",
	"token_type": "at+JWT",
	"exp": ACCESS_TOKEN_LIFETIME,
	"client_id": "CLIENT_ID",
	"iat": TIME_TOKEN_ISSUED,
	"aud": "https://external.pleo.io",
	"iss": "pleo.production",
	"jti": "TOKEN_ID"
}

Revoking Tokens

You can disable an integration by revoking the access token using the following request

https://auth.pleo.io/oauth/revoke

The user will have to complete the full authorization flow again to reenable the integration.