OAuth 2.0: flows to obtain an access token

OAuth 2.0[1] is an open standard authorization protocol that allows third parties (applications) to access data from a user without the user having to inform their credentials. Apps use this method to gain access to the account of a given user through a client ID or client secret (OAuth authentication keys).

If you wish to learn more, visit this website: http://oauth.net/2/.

Types of clients

In OAuth, there are two types of clients:

  • Confidential Client: these are clients that can ensure that no malicious users will get a client secret or client ID to try to pass for a valid application.

  • Non-Confidential Client: clients that cannot guarantee that a malicious user will get their client secret or client ID to try to pass for a valid application. In these cases, a callback URL is informed to ensure that the information returns only to the original app. Alternatively, the client ID time-to-live can be decreased by using a refresh token.

Ways to obtain an access token

There are different OAuth 2.0 flows, which demand distinct forms of obtaining an access token.

For some methods, you need to send an extraInfo. Values sent as extraInfo are exhibited in the Extra Fields of a token’s overview screen, which can be accessed by clicking the name of a token on the Access Tokens page.

Authorization Code

1. Generating an authorization code:

First, an app must have been created. With it, we can get the client ID, which is the first item we must inform via a POST request to this endpoint: <gateway URL>/oauth/grant-code.

The header must contain the following information:

Content-Type: application/json

We need to inform the following items in the body:

{
  "client_id": "f9212173-e705-373b-a698-61923e378359",
  "extraInfo": {},
  "redirect_uri": "string",
  "state": "string"
}
The client ID informed must be the same of the app created.

Once this is done, a response containing an authorization code is expected, as in the example below:

{
  "redirect_uri": "string?state=string&code=8748d39f-1d4f-311f-92c6-4b279db1b317"
}

2. Informing the authorization code to generate the access token:

You must perform a new POST request then, to this endpoint: <gateway URL>/oauth/access-token.

The header must contain the following information:

Authorization: Basic client_id:client_secret
This clientid:clientsecret must be a string converted to Base64, using the data from the app created.

Example of a header with the client_id and the client_secret converted to Base64:

Authorization: Basic ZjkyMTIxNzMtZTcwNS0zNzNiLWE2OTgtNjE5MjNlMzc4MzU5OjAyYWI1Mjg4LTkyZGItM2FiMy05OWZkLWZhYzRhZjg1N2Q4MQ==

In the body, we must inform the authorization code generated by the previous endpoint. You can use either x-www-form-urlencoded or JSON for the body, just remember to include the corresponding Content-Type header (application/x-www-form-urlencoded or application/json).

Include the following information in the body:

  • grant_type, with value authorization_code.

  • code, with the value received from the previous endpoint.

The access token will be generated and the following code will be returned:

{
  "access_token": "57f10f0e-3d2e-311f-a797-4011f66e1cbf",
  "refresh_token": "ca81cb16-43e4-3e96-aaea-4861e7791dc7",
  "token_type": "access_token",
  "expires_in": 3600
}

Authorization code with PKCE

As of the API Platform 4.6.1.0 release, we support PKCE in the Authorization Code flow.

PKCE (Proof Key for Code Exchange) is an OAuth extension that aims at making the Authorization Code flow more secure by preventing the interception attack — i.e., when a malicious app gains access to the authorization code in a non-TLS communication and uses the code to issue an access token. You can read more about it in the RFC 7636.

PKCE is not required, it’s up to the client to decide whether or not to use it in the Authorization Code flow. If you want to use PKCE, you must send a code_challenge with a code_challenge_method in the grant-code request and, in the request to obtain a token, send a code-verifier:

  • code-verifier: according to RFC 7636, "high-entropy cryptographic random STRING using the unreserved characters [A-Z] / [a-z] / [0-9] / "-" / "." / "_" / "~" (…​) with a minimum length of 43 characters and a maximum length of 128 characters".

  • code_challenge: code derived from the code_verifier via a transformation method (code_challenge_method).

  • code_challenge_method: transformation method by which the code_challenge is generated. There are two options:

    • plain: code_challenge = code_verifier

    • S256: code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))

      If the code_challenge_method is not passed, it is assumed to be plain.

To use PKCE, the client must include the following information in the requests:

  • in the body of the request to obtain an authorization code (/grant-code) described above, include the code_challenge and the code_challenge_method.

  • in the body of the request to obtain a token (/access-token) described above, include the code_verifier.

The authorization server does not validate if the code_challenge is following the high entropy that is recommended by the RFC, as this is the responsibility of the client. It is also not mandatory that PKCE be used in the Authorization Code flow. However, once the client sends the code_challenge when requesting an authorization code, the authorization server will require the code_verifier in the request to obtain the token. This code_verifier will be validated based on the code_challenge and code_challenge_method sent earlier and if the validation is not successful, the token will not be generated.

Refresh Token

The refresh token will be used to update an expired access token. To update a token, follow the steps below.

First, make a POST request to this endpoint: <gateway URL>/oauth/access-token.

The header should contain the following information:

Authorization: Basic client_id:client_secret
This clientid:clientsecret must be a string converted to Base64, using the data from the app created.

Example of a header with the client_id and the client_secret converted to Base64:

Authorization: Basic ZjkyMTIxNzMtZTcwNS0zNzNiLWE2OTgtNjE5MjNlMzc4MzU5OjAyYWI1Mjg4LTkyZGItM2FiMy05OWZkLWZhYzRhZjg1N2Q4MQ==

In the body, we must inform the refresh_token received by the previous endpoint (which generated the access token) and the grant type in the format x-www-form-urlencoded, as in this example:

grant_type=refresh_token&refresh_token=ca81cb16-43e4-3e96-aaea-4861e7791dc7

Finally, the access token will be regenerated and a code like the example below will be returned.

{
  "access_token": "ca81cb16-43e4-3e96-aaea-4861e7791dc7",
  "refresh_token": "677b881a-d0b6-3b29-b9a8-f0cdb50ce035",
  "token_type": "access_token",
  "expires_in": 3600
}

Implicit

The Implicit flow is used to obtain access tokens for public clients in an optimised way. It can operate across a private routing IRO alongside an access token. These clients are usually implemented on a browser using a script language, such as JavaScript.

As with the OAuth 2.0 Authorization Code, an app must have been created so that we can access the client ID. After that, make a POST request to the endpoint <gateway URL>/oauth/access-token.

It must contain the following header:

Content-Type: application/json

We must inform these items in the body:

{
  "grant_type": "implicit",
  "redirect_uri": "<URL>",
  "client_id": "<client ID>"
}
The client ID must be the same of the app created.
Note that the app must contain an extra field named redirect_uri, with a valid URL as its value, which must be informed when requesting the token (e.g.: http://example.demo.sensedia.com/). Access this page to see more information on creating and configuring apps, adding extra fields.

When the process is done, a response is expected, containing the URI and the access token, like the example below.

{
  "redirect_uri": "www.url.com?access_token=57f10f0e-3d2e-311f-a797-4011f66e1cbf",
  "expires_in": 3600
}

Client Credentials

Like the Implicit flow, Client Credentials does NOT generate a refresh_token. Therefore, it is not possible to update an access token when it expires.

When this flow is used, when creating a new access token, you should inform the app’s name and client ID into the token’s Extra Info field, informing all the values of the extra fields that are registered for that app as well. Access this page to see more information on creating and configuring apps, adding extra fields.

An app must have been created so that we can get the client ID and the client secret.

Then, it is necessary to make a POST request to this endpoint: <gateway URL>/oauth/access-token.

The request must contain the following header:

Authorization: Basic client_id:client_secret
This clientid:clientsecret must be a string converted to Base64, using the data from the app created.

Example of a header with the client_id and the client_secret converted to Base64:

Authorization: Basic ZjkyMTIxNzMtZTcwNS0zNzNiLWE2OTgtNjE5MjNlMzc4MzU5OjAyYWI1Mjg4LTkyZGItM2FiMy05OWZkLWZhYzRhZjg1N2Q4MQ==

In the body, we must inform the grant_type in the x-www-form-urlencoded format:

grant_type=client_credentials

Then, your access token will be generated and should be returned as in the example below.

{
  "access_token": "6c164a82-84a6-3bc4-8122-f777121a4f62",
  "token_type": "access_token",
  "expires_in": 3600
}

You can also create new extra fields when generating the access token. To do so, it is necessary to add the following header:

Content-Type: application/json

In the body, we must inform the grant_type and the extra fields, as in this example:

{
  "grant_type": "client_credentials",
  "extraInfo": {"value": "32423", "value2": "874yhgt3"}
}

Password

An app must have been created so that we can access the client ID and the client secret.

After that, you must make a POST request to this endpoint: <gateway URL>/oauth/access-token.

The header must contain this information:

Authorization: Basic client_id:client_secret
This clientid:clientsecret must be a string converted to Base64, using the data from the app created.

Example of a header with the client_id and the client_secret converted to Base64:

Authorization: Basic ZjkyMTIxNzMtZTcwNS0zNzNiLWE2OTgtNjE5MjNlMzc4MzU5OjAyYWI1Mjg4LTkyZGItM2FiMy05OWZkLWZhYzRhZjg1N2Q4MQ==

In addition to the grant_type, the body must contain two other pieces of information that use the userDirectory. They are the user’s login and password, which can be from an LDAP or a REST, and must be in the x-www-form-urlencoded format:

grant_type=password&username=<user>&password=<password>

If the user and password are valid in LDAP or REST, the return of the access token should resemble the following example:

{
  "access_token": "6c164a82-84a6-3bc4-8122-f777121a4f62",
  "token_type": "refresh_token",
  "expires_in": 3600
}
For the features above to apply to your app, you must configure an API Identity.
In the case of LDAP, the user must be informed in the User-Principal-Name format (e.g., test@da.sa).
The oauth.grantTypes.resourceOwnerPassword.userDirectory property is no longer required.

JWT

"JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA." (https://jwt.io/)

Before we make the call to generate the JWT token, we need to make a call to generate the Authorization Code. To know how to generate it, click here.

In the JWT flow, an app must have been created to that we can access the client ID and the client secret.

Then, you must make a POST request to this following endpoint: <gateway URL>/oauth/access-token.

The header should contain the following information:

Authorization: Basic client_id:client_secret
This clientid:clientsecret must be a string converted to Base64, using the data from the app created.

Example of a header with the client_id and the client_secret converted to Base64:

Authorization: Basic ZjkyMTIxNzMtZTcwNS0zNzNiLWE2OTgtNjE5MjNlMzc4MzU5OjAyYWI1Mjg4LTkyZGItM2FiMy05OWZkLWZhYzRhZjg1N2Q4MQ==

In the body, we must inform the code generated by the grant-code endpoint and the grant type in the format x-www-form-urlencoded, as in this example:

grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&code=8748d39f-1d4f-311f-92c6-4b279db1b317

Your access token will then be generated again and should be returned as in the example below.

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJsb2NhbGhvc3QiLCJpc3MiOiIxNzIuMTguMC4xIiwic3ViIjoiOWI1Zjc3MWUtNzgyZC0zNTEwLWI2YmEtMzZlOWM2NWJmZDVkIiwiZXhwIjozNjAwLCJpYXQiOjE1Mjg5MTg2MzcsIkFwcDogIjoiUmljYXJkb0FwcCIsIkNvZGU6ICI6IjRlNWIyMTEzLTJkYzYtM2RlNi1iN2ZkLWNkOTYxOTMxZWQyOSIsImxvZ2luIjoidXNlci5sb2dpbiJ9.bhvFpiZ6em9tUgpHxGQGuH7cmvMy4I7STJDRBUybuPM",
  "token_type": "access_token",
  "expires_in": 3600
  }

With the code generated, you will need to add the JWT interceptor to the API flow. It will be responsible for validating the token. See more about this interceptor here.

OpenID

The OpenID flow allows users to use an existing credential to access multiple websites without the need to create new passwords. This enhances users' security because their password is supplied only to one provider that they trust, which then confirms their identity and concedes access to sites and apps that they want to use.

To use the OpenID flow, you need to create the Google OpenID API. Click here for instructions on how to create the API.

It is also necessary that an app has been created. With it, we can access the client ID, which will be the first item to be informed via a POST request to this endpoint: <gateway URL>/google/oauth/openid/redirect.

The request must contain the following headers:

Content-Type : application/json

client_id :  client_id

In the body, we must inform the following item:

{
  "extraInfo": {}
}
The client_id must be the same as the app created.

Once this is done, there should be a response containing an authorization code, like in the example below.

{
  "redirect_uri": "string?queryParams"
}

Then you must access the redirect_uri, which gives access to an authentication page from your provider. Logging in will redirect automatically following the access token values.

Access token and refresh token revocation

Revocation inactivates a token that is still valid but no longer needed. After revocation, the token will not be accepted in requests to APIs.

You can use the /revoke endpoint of the "OAuth 2.0" API to revoke an access token or refresh token. In both cases, all tokens are revoked — that is, if you revoke an access token and there is a refresh token associated with it, it is also revoked, and if you revoke a refresh token, the access token associated with it is also revoked.

To revoke a token, you must send a POST request to <gateway URL>/oauth/revoke. The request must contain the Authorization header:

Authorization : Basic client_id:client_secret
This clientid:clientsecret must be a string converted to Base64, using the data from the app created.

Example of a header with the client_id and the client_secret converted to Base64:

Authorization: Basic ZjkyMTIxNzMtZTcwNS0zNzNiLWE2OTgtNjE5MjNlMzc4MzU5OjAyYWI1Mjg4LTkyZGItM2FiMy05OWZkLWZhYzRhZjg1N2Q4MQ==

In the body, pass the following information in the format x-www-form-urlencoded:

token=<valor>&token_type_hint=access_token

OR

token=<valor>&token_type_hint=refresh_token

Note that the token_type_hint is not required (because the token is found by the value entered), but it does make the revocation operation faster.

Thanks for your feedback!
EDIT
How useful was this article to you?