Supported authorization grant types

An authorization grant is (roughly) equivalent to an admission ticket. An admission ticket provides access to an event of some kind: a baseball game, a concert, an art exhibition. Similarly, an authorization grant provides access to a protected resource: for example, in Hosted Login you can’t manage your user profile unless you have an access token that provides access to that profile. And where does that access token come from? You got it: from an authorization grant.

To extend our metaphor a little, admission tickets can come from different sources: you might buy a ticket from an online ticket agency or from an authorized ticket reseller or from the stadium box office. In the same way, authorization grants can come from different sources; for example, Hosted Login supports the following authorization grant types:

  • authorization_code. Clients receive an authorization code they can exchange at the token endpoint for an access token, a refresh token, and an identity token.

  • implicit. The authorization endpoint directly issues clients an access token and/or an identity token, and does so without requiring the client to visit the token endpoint.

  • refresh_token. Clients exchange a refresh token for a new access token (a fairly common exchange considering the fact that access tokens have, at most, a one-hour lifespan).

  • client_credentials. Clients obtain an access token by supplying the credentials of an OIDC confidential client rather than the credentials of an individual user. In Hosted Login, this grant enables you to obtain the configuration access tokens required to call the OIDC Configuration APIs.


📘

Depending on how you want to look at it, Hosted Login also supports the hybrid grant type. However, because the hybrid grant is really just a combination of the authorization_code grant and the implicit grant, it’s not listed as an “official” grant type. Instead, by supporting both the authorization _code and the implicit grants that means that Hosted Login also supports the hybrid grant.


In this documentation, we’ll explain what each of these grant types does and how it works. We’ll also supply some background information on how to include different grant types in an authorization request, as well as information on managing the grant types that can be employed in your organization.


Reference grant types when you contact the token endpoint

If you request a token directly from the token endpoint (which is the case if you are using either the refresh_token or the client_credentials grant) then your request must include the grant_type parameter. As implied by the preceding sentence, the grant_type parameter is not used when making an authorization_code or an implicit grant request. That’s because those requests are directed to the authorize endpoint rather than the token endpoint. In those two cases, your authorization request uses the response_type parameter instead of the grant_type parameter.

As we noted, however, if you are contacting the token endpoint then your request must include the grant_type parameter followed by the grant being requested. For example, this syntax requests the client_credentials grant:

grant_type=client_credentials

If you make an authorization request and receive an “unsupported grant type” error, that usually means one of two things:

  1. You mistyped the grant name; for example, you requested the client_credential grant instead of the client_credentials grant.

  2. The requested grant type isn’t included in the allowedGrantTypes property of your token policy. See Managing Allowed Grant Types (i.e., the next section of this documentation) for more information.


Manage allowed grant types

By default your Hosted Login token policies support all four of the allowed grant types. You can verify this by using the GET method to call the /tokenPolicies/{tokenPolicyId}/allowedGrantTypes endpoint and return information about the grant types supported by a given token policy. (As you probably inferred, token policies determine which grant types you can use.) For example, the following Curl command returns the grant types supported by token policy a7f902b3-6e63-4f60-87a6-6cf5a1bc8ff4:

curl -L -X GET \
  'https://v1.api.us.janrain.com/e0a70b4f-1eef-4856-bcdb-f050fee66aae/config/tokenPolicies/a7f902b3-6e63-4f60-87a6-6cf5a1bc8ff4/allowedGrantTypes' \
  -H 'Authorization: Bearer 0yDPA59d6roaLCfodHSbrtBMkQxVe-G3AQ0oHEgWK-Y272EUQtP_S0SV3YL2icV5'

In this case, we get back the following (note that the client_credentials grant type is missing):

[
    "authorization_code",
    "refresh_token",
    "implicit"
]

So what does it mean to say that a token policy only supports these three grant types? Well, suppose you make an authorization request using a login client associated with the preceding token policy. Let’s further suppose that your authorization request references the client_credentials grant type (grant_type=client_credentials). The client_credentials grant is a valid grant type, which means that it’s supported by Hosted Login. And yet, your authorization request is still going to fail with an unsupported_grant_type error. That’s because you can’t reference a grant type that isn’t included in the allowedGrantTypes property of the relevant token policy.


📘

What’s a “relevant” token policy? That’s simply the token policy associated with the OIDC login client used to make your authorization request.


Unless, and until, you add the client_credentials grant to your list of supported grant types any request referencing that grant is going to fail.

Fortunately, it’s easy to add grant types to a token policy: all you have to do is employ the /tokenPolicies/{tokenPolicyId}/allowedGrantTypes endpoint and the PUT method. When calling this endpoint, be sure to include all the grant types you want to allow in the call’s request body parameter. (And make sure you format those grant types as a JSON array.) For example, the following call adds all four allowed grant types to token policy 5a1e3d0e-7a57-48ce-aa9c-b303345f5747:

curl -L -X PUT \
  'https://v1.api.us.janrain.com/e0a70b4f-1eef-4856-bcdb-f050fee66aae/config/tokenPolicies/5a1e3d0e-7a57-48ce-aa9c-b303345f5747/allowedGrantTypes' \
  -H 'Authorization: Bearer cBviooa_cmjNcax6MULDgDepVDN6xLueoWlPfw2x2vMdaNUyWCSqcXAmRjV5tw4H' \
  -H 'Content-Type: application/json' \
  --data-raw '[
    "authorization_code",
    "implicit",
    "refresh_token",
    "client_credentials"
]'

As you can see, the preceding request body includes all four allowed grant types, including the three (authorization_code, refresh_token, and implicit) already supported by the token policy. We included all four grant types because the PUT method replaces the existing grant types with whatever happens to be in the request body of your API call. For example, suppose we wanted to add the client_credentials grant type and, in an attempt to do that, we made the following API call:

curl -L -X PUT \
  'https://v1.api.us.janrain.com/e0a70b4f-1eef-4856-bcdb-f050fee66aae/config/tokenPolicies/5a1e3d0e-7a57-48ce-aa9c-b303345f5747/allowedGrantTypes' \
  -H 'Authorization: Bearer cBviooa_cmjNcax6MULDgDepVDN6xLueoWlPfw2x2vMdaNUyWCSqcXAmRjV5tw4H' \
  -H 'Content-Type: application/json' \
  --data-raw '[
    "client_credentials"
]'

That’s a valid API call, but it’s also an API call that won’t add the client_credentials grant to the collection of allowed grant types. Instead, the preceding API call replaces the entire collection with the grant type client_credentials; if we use the GET method to look at our allowed grant types this is what we’ll see:

[
    "client_credentials"
]

In order to add the client_credentials grant type we need to include all the other grant types we want to support as well:

curl -L -X PUT \
  'https://v1.api.us.janrain.com/e0a70b4f-1eef-4856-bcdb-f050fee66aae/config/tokenPolicies/5a1e3d0e-7a57-48ce-aa9c-b303345f5747/allowedGrantTypes' \
  -H 'Authorization: Bearer cBviooa_cmjNcax6MULDgDepVDN6xLueoWlPfw2x2vMdaNUyWCSqcXAmRjV5tw4H' \
  -H 'Content-Type: application/json' \
  --data-raw '[
    "authorization_code",
    "refresh_token",
    "implicit",
    "client_credentials"
]'

Needless to say, that’s an important point to keep in mind.

Incidentally, this is also how you remove grant types from a token policy. Did you decide not to support the implicit grant type after all? That’s fine; just re-run your API call, making sure to leave out the implicit type:

curl -L -X PUT \
  'https://v1.api.us.janrain.com/e0a70b4f-1eef-4856-bcdb-f050fee66aae/config/tokenPolicies/5a1e3d0e-7a57-48ce-aa9c-b303345f5747/allowedGrantTypes' \
  -H 'Authorization: Bearer cBviooa_cmjNcax6MULDgDepVDN6xLueoWlPfw2x2vMdaNUyWCSqcXAmRjV5tw4H' \
  -H 'Content-Type: application/json' \
  --data-raw '[
    "authorization_code",
    "refresh_token",
    "client_credentials"
]'

It’s as easy as that.


authorization_code (the Authorization Code grant)

img

Authorization request syntaxresponse_type=code
Authorization request is sent toThe authorization endpoint (e.g., https://v1.api.us.janrain.com/e0a70b4f-1eef-4856-bcdb-f050fee66aae/login/authorize)

After a successful authentication, a user is issued an authorization code; this code can then be exchanged at the token endpoint for an access token, a refresh token, and an identity token. An authorization request that uses the authorization_code grant type will look similar to the following:

https://v1.api.us.janrain.com/e0a70b4f-1eef-4856-bcdb-f050fee66aae/login/authorize
    ?client_id=64430515-01ea-4f5d-82e4-c36161af0093
    &redirect_uri=http://localhost
    &scope=openid
    &code_challenge=ufBhlb8CfzV874maXPFHIguVkjBYssKgi8L5Ec
    &code_challenge_method=S256
    &response_type=code
    &state=b04jyxi6W1uRgSuFbX-jPNV5KG_hAdJrBjohCUsk3RU

If your API call succeeds, you’ll get back an authorization code that will look similar to this:

http://localhost/?code=Abh7F4HhxZ-Wy2Dk&state= b04jyxi6W1uRgSuFbX-jPNV5KG_hAdJrBjohCUsk3RU

Note that, to be a true Authorization Code grant, your response type can only be set to code. If you include multiple response types (for example, response_type=code token) then, technically speaking, you’re requesting an implicit or hybrid grant instead.

The authorization_code grant – recommended any time you’re authenticating and authorizing end users – is covered in much more detail in the article Authorization code + PKCE grant type.


implicit (the Implicit grant)

img

Authorization request syntaxresponse_type=token response_type=id_token response_type=token id_token
Authorization request is sent toThe authorization endpoint (e.g., https://v1.api.us.janrain.com/e0a70b4f-1eef-4856-bcdb-f050fee66aae/login/authorize)

The implicit grant type provides a way to receive an access token and/or an identity token directly from the authorization endpoint itself: there’s no need to visit the token endpoint and exchange an authorization code for a set of tokens. In fact, authorization codes aren’t even used with the implicit grant type.

The implicit grant type makes it easy to get an access token or an identity token, but there is at least one major drawback to taking this approach: you don’t get a refresh token when you make an authorization request by using the implicit grant. That means that, if you receive an access token using this grant type and your access token expires, you’ll have to go back through the authentication process in order to obtain a new token.

The implicit grant was originally designed for user agent applications: JavaScript applications running within a web browser. Because of security risks, (for example, anything passed from the server to the client – such as an access token – is visible to the browser) the implicit grant has largely been superseded by PKCE (Proof Key for Code Exchange). However, for backward compatibility reasons and to provide full support for the OAuth standard, Hosted Login does allow you to use the implicit grant.

Even though it’s not necessarily recommended.

When making an implicit grant request, use the parameters included in the following table. Note that you don’t initiate the Implicit grant by using the grant_type parameter. Instead, the implicit grant is invoked if you set the response type to any one of the following:

  • token (requests an access token)
  • id_token (requests an identity token)
  • token id_token (requests both an access token and an identity token)

 

ParameterDescription
response_typeMust be set to one of the following:
token>br>id_token
token Id_token
client_idUnique identifier of the OIDC login client used during the authorization request.
redirect_uriSpecifies the URL of the page the user is redirected to following a successful authentication and login. For example:redirect_uri=h<span>ttp</span>s://identitydocs.akamai.com/redirectNote that the specified URL must exactly match one of the URLs listed in the OIDC login client’s redirectURIs property. If the URL isn’t included in the redirectURIs property then the authorization request fails with an Invalid client error and the user won’t be authenticated.
scopeOIDC scopes being requested. Scopes specify the user profile information you’d like to make available from the userinfo endpoint. All requests must include the openid scope.
stateA random string that helps guard against cross-site request forgery (CSRF) attacks. For example, suppose your authentication request includes the following state parameter and parameter value: state=GA-ISU_6CwFn0tQTFiYD_-Gvy39Nb6iTdugdGIzTUngAfter a successful authentication you’ll be redirected to the URL specified by the redirect_uri parameter. If you were redirected by the authorization endpoint then the state parameter and value will be included in that URI:h<span>ttp</span>s://identitydocs.akamai.com/redirect_uri?code=AH6S2WG_ XchALC-p&state=GA-ISU_6CwFn0tQTFiYD_-Gvy39Nb6iTdugdGIzTUngIf the state parameter in the redirect URI doesn’t match your original parameter value then you might be the victim of a CSFR attack (defined as an attack in which malware tries to trick you into carrying out some sort of action you never intended to carry out). In that case, you should restart the authentication process.
nonceA random string added to the authorization request. This string (and its value) will be included in your identity token. If the nonce used in the authorization request doesn’t match the nonce claim found in the identity token there’s a good chance that the ID token isn’t valid. The nonce parameter must be included on any authorization request that includes id_token among the response types.
code_challengeHashed and encoded value generated by the client. This value should be verified before the client is allowed to exchange an authorization code for a set of tokens.
code_challenge_methodHashing algorithm used to generate the value of the code_challenge parameter. For Hosted Login, this will always be S256.

An authorization request that uses the Implicit grant type will look similar to the following:

https://v1.api.us.janrain.com/e0a70b4f-1eef-4856-bcdb-f050fee66aae/login/authorize?
    client_id=64430515-01ea-4f5d-82e4-c36161af0093
    &redirect_uri=http://localhost
    &scope=openid
    &code_challenge=ufBhlb8CfzV874maXPFHIguVkjBYssKgi8L5Ec
    &code_challenge_method=S256
    &response_type=token
    &state=LA6fKYw_1_7x_xrSpJQlStcu5YiqbycKE8QjVWEmeng

If the preceding request succeeds, you’ll get back an access token. For example:

http://localhost/
    #access_token=q_g8T48bPOEd9KB9mgkDz2w2O0wM8aCGC4fiQm7RTajFnKfdzPphgoEVFUBzlZsd
    &expires_in=3600
    &scope=openid+%252A%253Alogin%252Fauthorize+.%253Alogin%252Fprovider%252F%252A%252Fauthorize+.%253Alogin%252Fprovider%252F%252A%252Fcallback+%252A%253Alogin%252Ftoken+%252A%253Aprofiles%252Foidc%252Fuserinfo+.%253Aprofiles%252Foidc%252Fuserinfo+%252B%253Aprofiles%252Foidc%252Fuserinfo
    &state=LA6fKYw_1_7x_xrSpJQlStcu5YiqbycKE8QjVWEmeng
    &token_type=Bearer

refresh_token (the Refresh Token grant)

img

Authorization request syntaxgrant_type=refresh_token
Authorization request is sent toThe token endpoint (e.g., https://v1.api.us.janrain.com/e0a70b4f-1eef-4856-bcdb-f050fee66aae/login/token)

Provides a way to exchange a refresh token for a new access token. Typically this grant is invoked after a user is denied access to a resource with an invalid_token error and the error description “The access token expired”. When this error occurs, the refresh_token grant can be used to return a new access token and give the user access to the resource.

When making an authorization request using the refresh_token grant, you must include the following items in the request body of your API call, formatted as x-www-form-urlencoded:

ParameterDescription
grant_typeMust be set to refresh_token.
client_idUnique identifier of the OIDC login client used when the access token was issued.
refresh_tokenValue of the refresh token. For example:R3__gSL_lEFQwXwCNCqNylggyPI4qmKrE3wH3AbfA1npS2zemTO-nIgNbYk-pM3z

A Curl command for calling the refresh_token grant will look similar to the following:

curl -L -X POST \
  'https://v1.api.us.janrain.com/e0a70b4f-1eef-4856-bcdb-f050fee66aae/login/token' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'grant_type=refresh_token' \
  --data-urlencode 'client_id=64430515-01ea-4f5d-82e4-c36161af0093' \
  --data-urlencode 'refresh_token=-AAefW2D16woUbjHUrbIHtIs9Kila-RaBuprupsSMwU4ggC4Y3jH7RQ0DN096wzA'

Note that no authorization is required to call the refresh_token grant. In fact, if you do include authorization of some kind your API call fails with a “request includes multiple client credentials” error.

If your API call is successful you should get back a new set of Hosted Login tokens:

{
    "access_token": "glT-tctFU41_Zu7pj3i3-S_rL-CZo33Ol4CqsxIn2pxX7y4H1WakBQ_LowTD279E",
    "refresh_token": "XflqBRF-MDEQy4pLEKsXZs6_hg5so8EqFKmlDHxGFh8PqKykUjNqYOREz-zHOdF_",
    "expires_in": 3600,
    "token_type": "Bearer",
    "scope": "openid",
    "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjNhZjQ3ZTNmNmE0YmQwNTY5NzgyZmVlNWMxZjg2MjNhM2ZmMGQ3OGYiLCJ0eXAiOiJKV1QifQ.eyJhdF9oYXNoIjoiT3AxSnZyMVliekx6SGZjbkFmdVdydyIsImF1ZCI6WyI2NDQzMDUxNS0wMWVhLTRmNWQtODJlNC1jMzYxNjFhZjAwOTMiXSwiZXhwIjoxNjExODU1MzE1LCJnbG9iYWxfc3ViIjoiY2FwdHVyZS12MTovL3NlLWRlbW9zLWdzdGVtcC51cy1kZXYuamFucmFpbmNhcHR1cmUuY29tLzc5eTRtcWYycnQzYnhzMzc4a3c1NDc5eGR1L0dSRUdfREVNTy8wYzAyYTg5YS1mMjk2LTQ1NTAtOWZhZC0wNTVjZjg3MDk5ZjQiLCJpYXQiOjE2MTE4NTE3MTUsImlzcyI6Imh0dHBzOi8vdjEuYXBpLnVzLmphbnJhaW4uY29tL2UwYTcwYjRmLTFlZWYtNDg1Ni1iY2RiLWYwNTBmZWU2NmFhZS9sb2dpbiIsImp0aSI6Im1ZT0ZxT0NCckpWdFNtcGtfYmdta2Z1YSIsIm9yZ2FuaXphdGlvbiI6IkFrYW1haSIsInN1YiI6IjBjMDJhODlhLWYyOTYtNDU1MC05ZmFkLTA1NWNmODcwOTlmNCJ9.fuGnK61mHI6s8_01FXlsxcUvEur74qStZ-9R7PzgaKksOmsiUqaGTmc-zvkYtJ6WgR1bxchesJ1nK6sA4R2lbfJkI9h4p0wIC4GeuthF1VVnBtkmPUFebmr85pMM8ZFbJFh7wFDLE50iHgAk1Ax9Bl9-bqGuFFRkoPmGMahwYE1CIqu1JI-056SLVuiBjMXPG9qNaivGkOsanmg4QQ8mSjgV9HZl8fNxk8EBpsLm9EDcdoX4ci70Yk7LNXR1dNX-5PJuJpCs9DGuzkw3WGVY-SygPjyrW3qjLLWHR1bbbXClZYitRZGsU5SCQ1sAdy-HE46-FTHQwFPDpjRmoj6ZrQ"
}

client_credentials (the Client Credentials grant)

img

Authorization request syntaxgrant_type=client_credentials
Authorization request is sent toThe token endpoint (e.g., https://v1.api.us.janrain.com/e0a70b4f-1eef-4856-bcdb-f050fee66aae/login/token)

With the client_credentials grant type, the client requests an access token for itself rather than requesting an access token for a specific user. In Hosted Login, this grant is typically used to obtain an administrative access token that can be employed to call the OpenID Connect Configuration APIs.

When you create an authorization request that uses the client_credentials grant, you don’t enter your own credentials (e.g., your own email address and password). Instead, you enter the client ID and client secret of a confidential OIDC client. (And, yes, you have to use a confidential client: that’s because public clients don’t have a client secret that can function as a password.) If Hosted Login issues you an access token that token won’t be issued because of who you are: with this type of grant, Hosted Login doesn’t know, or care, who you are. All it cares about is whether the client credentials you provided are valid.

The following Curl command uses a client_credentials grant to receive a configuration token that can be used to call the OIDC Configuration APIs:

curl -L -X POST \
  'https://v1.api.us.janrain.com/e0a70b4f-1eef-4856-bcdb-f050fee66aae/login/token' \
  -H 'Authorization: Basic YmNjZjEwNjgtNDNhMS00ZmQ1LWE5ZTctZGFjNmE4YjVjNjdlOmNBVFhCbHB4c0w4T1FxbkNGM1FTbS00WUJ0TFVpLTB2b2JCT1dXd2JWVWVYT1VQbHpTaXBKN3RxWW9sUVF0aWFIOENfQTlLc2N6eGpTc21pRWxhZFd3' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'grant_type=client_credentials' \
  --data-urlencode 'scope=*:**'

If your API call is successful you’ll get back an access token but no refresh token or identity token (you won’t get an identity token because the access token isn’t tied to a specific user):

{
    "access_token": "zr-35mkFDicgtrH611A-yI_isueIM3LKqlryNgRPWmXldw85nL7RmI-5yt1VcNBN",
    "expires_in": 3600,
    "token_type": "Bearer",
    "scope": "*:**"
}

For more information about the client_credentials grant, see the Hosted Login article Get started.