In the Authorization Code Flow, a Remote Company Admin (resource owner) authorizes an API Partner to manage its resources through the API. All operations performed by the API Partner are on behalf of the Company Admin who authorized the integration. Therefore the access_token
obtained through this flow only allows managing the company itself.
The flow is extensive but enables Remote and the API Partner to exchange tokens securely. At the end of the process, the API Partner can fetch a valid Access Token on behalf of an existing Remote Company without exposing the tokens to the external world.
The flow described below enables an existing Remote Company to grant permissions for an API Partner (through the partner's Client Application) to manage its resources. This sequence diagram shows a visual of the flow described below.
<aside>
💡 Passing the access_token
in the Authorization header is the only way to act on behalf of a Company Admin via the Remote API.
</aside>
The first step is to redirect the user to the authorization page. This page is in the Authorization Server. Usually, it is done when the user clicks a button or a link. The link should be built like this:
<https://gateway.remote-sandbox.com/auth/oauth2/authorize?<configuration> query strings>
<aside>
💡 When you’re ready to release your integration, replace the domain with https://gateway.remote.com
</aside>
Here are the allowed configuration query strings:
client_id
: It's a required param. API Partners should provide their CLIENT_ID
in plain text. This is the same client ID used in the Client Credentials Flow. Please, notice that the CLIENT_SECRET
should never be exposed externally. The CLIENT_ID
is the sole piece of information that must be used in this case.redirect_uri
: It's a required param. In the process of registering the API Credentials, API Partners are asked about the redirect URIs. For security reasons, we only allow URIs that exactly match one of the provided during Client Registration.state
: It's a required param. This param is crucial for security. The API Partner must generate a random string and pass it on the state
param. When the Remote API redirects the user to the provided redirect_uri
, it will include the untouched state
value so that the API Partner can ensure the request's origin is trustful.scope
: It's an optional param. The scope tweak which permissions are being granted with the authorization. For now, the only valid value is https://gateway.remote.com/company.manage
which grants permissions for managing the company data and its employments. The value doesn't change if you are using the sandbox domain.$ echo $CLIENT_ID
9c62f10ef475f55c982328eaa8f64fa8
# Using openssl to generate a random string with 16 bytes.
$ openssl rand -hex 16
c97b8fa15f7f8ba064b338779b8eecab
<https://gateway.remote-sandbox.com/auth/oauth2/authorize?client_id=9c62f10ef475f55c982328eaa8f64fa8&redirect_uri=https://example.com/callback&state=c97b8fa15f7f8ba064b338779b8eecab>
<aside>
💡 When you’re ready to release your integration, replace the domain with https://gateway.remote.com
</aside>
If the Company Admin user is not signed in, the Authorization Server redirects the browser session to the sign-in page in Remote UI. After signing in, the session is redirected back to the authorization page.
If the signed-in user has a role other than Admin, a page with a 403 status (Forbidden) is displayed for the user. In order to prevent this error, Client Applications can instruct their users to ask for authorized personnel to perform it.
If all the params provided in the authorization URL are correct, the Company Admin is presented with the following page:
The Company Admin is able to perform one of two actions: approve or deny the authorization.
After clicking Approve, the Authorization Server redirects the Company Admin to the URL provided in the redirect_uri
param. It will, however, add additional query parameters to indicate that the request was successful. They are:
state
: it contains the same value passed for the authorization endpoint described in section 1.code
: this is a token that must be exchanged for the authorization's refresh_token
. This token doesn't need to be stored as it is for one-time use and expires within 5 minutes.The redirect URL would look like this:
<https://example.com/callback?state=c97b8fa15f7f8ba064b338779b8eecab&code=dc518e245b9157d6e658a45d7b3c1188e67bc37c>...
Although it looks like this is the end of the process, it is not. The code
parameter needs to be exchanged for a refresh_token
. Learn how to perform it in the following section.
After receiving a successful callback, the Client Application needs to exchange the authorization code for a refresh token. A refresh token, as the name says, is able to retrieve a valid access token after it expired.
The exchange happens in a POST request to the Authorization Server as follows:
POST
request to https://gateway.remote-sandbox.com/auth/oauth2/token
<client_id>:<client_secret>
Authorization: Basic <client_id_and_client_secret_encoded_in_base64>
Content-Type: application/x-www-form-urlencoded
header in the requestgrant_type
filled with authorization_code
— it's a constant valuecode
filled with the value in the callback's query string (in the 2a step)Assuming your CLIENT_ID=your_client_id
and CLIENT_SECRET=your_client_secret
, an example of what your request should look like is shown below.
$ echo -n "your_client_id:your_client_secret" | base64
eW91cl9jbGllbnRfaWQ6eW91cl9jbGllbnRfc2VjcmV0
$ curl --location \\
--request POST '<https://gateway.remote-sandbox.com/auth/oauth2/token>' \\
--header 'Authorization: Basic eW91cl9jbGllbnRfaWQ6eW91cl9jbGllbnRfc2VjcmV0' \\
--header 'Content-Type: application/x-www-form-urlencoded' \\
--data-urlencode 'grant_type=authorization_code' \\
--data-urlencode 'code=dc518e245b9157d6e658a45d7b3c1188e67bc37c...'
<aside>
💡 When you’re ready to release your integration, replace the domain with https://gateway.remote.com
</aside>
The response to this request should look like the following JSON:
{
"access_token": "eyJraWQiOiIrRHF3Y1A4TU80bEMrN1NxSVQxSVcHHL6LLZH0o_xWvoUG...",
"company_id": "3718b8ba-55d3-4fa6-ae45-91cd43b67997",
"refresh_token": "84224550-dc8f-4153-a7cd-4f38c7ef90da",
"expires_in": 3600,
"token_type": "Bearer",
"user_id": "e25c2e12-be43-4964-ac00-40ddfbd896c4"
}
The response payload returns a valid access_token
of the type Bearer
. It also includes the refresh_token
. This information must be stored securely by the Client Application and used to fetch access tokens as described in the next section. The response payload also includes the user_id
and company_id
which won’t change so the client application can also store this for future reference.
<aside> 💡 The access token will be valid for 3600 seconds (one hour), so we recommend that the caller fetch a new access token before the current one expires (e.g. every 55 minutes). Please note that there is no limit to the number of access tokens that can be used at the same time. Please refer to the Refresh Token Flow article for instructions on issuing a valid access token.
</aside>
When the access_token
expires, the Client Application needs to request a new one. Follow the Refresh Token Flow instructions in order to obtain it.
This sequence diagram shows a visual of the alternative flow described below.
During steps 8 and 9, the Company Admin can either approve or deny the integration. If the Company Admin clicks "Deny", the Authorization Server redirects the session to the provided redirect_uri
with three query strings. They are:
error
: the value is always “denied.”error_message
: the value is "The authorization was denied."state
: it contains the same value passed for the authorization endpoint described in section 1.The redirect URL would look like this:
<https://example.com/callback?state=c97b8fa15f7f8ba064b338779b8eecab&error=denied&error_message=*The%20authorization%20was%20denied*>
At this point, the Client Application can display an error telling the User that the integration was denied.
Notice that the code
parameter is not added to the redirect URL, which means the Client Application won't be able to exchange it for a refresh token. The flow ends after it but the User may restart the process at any point. However, a new state
must be provided when sending the user to the authorization page.
refresh_token
. What should I do?The authorization code expires in 5 minutes. If for some reason the Client Application takes more than that to exchange for a refresh token, the whole flow needs to be restarted.
state
query parameter?The state
query parameter must be a random and unique string. It doesn't have any length specifications. We recommend it to have at least 8 characters. You can use MD5, SHA1, UUID, or another algorithm to generate those random strings.
With the authentication code in hand, you need to exchange it for a refresh_token
. The authentication code is valid for five minutes. After the expiration, you need to restart the flow.
Refresh tokens must be stored by the Client Application securely and used to issue new access tokens.
If you don't exchange your authentication code for a refresh token, the process is not complete. It means the Client Application won't be able to manage the company and employment resources of the user.