OAuth Flows

The OAuth protocol uses different flows to to setup tokens, as well as different ways how tokens can be used. This chapter is a summary of the different flows that establish Access Tokens, in relation to the Curity Identity Server. The actors that are used, are the Resource Owner (RO), the Client (C), the Resource Server (RS) and the Authorization Server (AS).

The full specification of OAuth is in RFC 6749.

Code

The Code flow is about a Resource Owner that authorizes an access request from the Client with the Authorization Server, resulting in a code that represents that delegated authorization. The user hands over the code to the Client, that uses it on a backchannel with the Authorization Server to exchange it for an OAuth Access Token.

This flow uses two endpoints on the Authorization Server, the oauth-authorize and the oauth-token endpoint.

It is split in two separate requests. The first is done in the front-channel in the browser as a regular GET request to the oauth-authorize endpoint.

GET request parameters:

Attribute Required Default value Description
scope No No Scope The scopes, space separated, to include in the token. Must be a subset of the scopes configured on the client.
state No No State The state will be returned in the final redirect
response_type Yes None Must be set to code
client_id Yes None The client id of the requestor.
redirect_uri Maybe   If only one redirect_uri is configured on the client this is not required if the openid scope is _not_ included. Otherwise it should be given.
code_challenge Maybe None The proof key code challenge. A client can be configured to require this attribute.
code_challenge_method No plain The method used to transform the code verifier into the code challenge. Supported values are plain and S256.

The second request is done as a server-side POST request with the content type application/x-www-form-urlencoded to the oauth-token endpoint. In this call the client needs to authenticate itself using its client credentials.

POST request parameters

Attribute Required Default value Description
scope No No Scope The scopes, space separated, to include in the token. Must be a subset of the scopes configured on the client.
grant_type Yes None Must be set to authorization_code
code Yes None The authorization code retrieved in the first call to the server.
client_id No None The client id of the requestor. If not set basic auth must be used
client_secret No None The secret of the client. If not set, basic auth must be used
redirect_uri Maybe   If the redirect_uri parameter was given in the GET request, it must also be given here.
code_verifier Maybe None The proof key code verifier used to generate the code challenge (using the code challenge method) sent in the authorization request. Required, if a code_challenge was sent in the authorization request.

Proof Key for Code Exchange

OAuth public clients are susceptible to the authorization code interception attack (RFC 7636).

In this attack, the attacker intercepts the authorization code returned from the authorization endpoint within a communication path not protected by Transport Layer Security (TLS), such as inter-application communication within the client’s operating system; e.g. custom protocol handlers. Once the attacker has gained access to the authorization code, it can use it to obtain the access token.

To mitigate this attack, a unique “code verifier” is created client-side for every authorization request; which is transformed into a “code challenge” that is sent to the authorization server. The authorization code obtained is then sent to the token endpoint together with the “code verifier”, where it is compared with the previously received “code challenge”; performing proof of possession of the “code verifier” by the client.

Implicit

The Implicit flow is also about the Resource Owner authorizing the access request from the Client with the Authorization Server, like the Code flow, but it does not respond with a code, but instead it provides the OAuth Access Token directly.

This flow is optimized for JavaScript-based Clients, and uses only the oauth-authorize endpoint on the Authorization Server.

The implicit flow is available on the oauth-authorize endpoint and is accessed with a GET request in the browser. The following request parameters are supported in the query string:

Attribute Required Default value Description
scope No No Scope The scopes, space separated, to include in the token. Must be a subset of the scopes configured on the client.
state No No State The state will be returned in the final redirect
response_type Yes None Must be set to token
client_id Yes None The client id of the requestor.
redirect_uri Maybe   If only one redirect_uri is configured on the client this is not required. Otherwise it should be given.

The response is given as a fragment parameter in a redirect back to the client on a predefined or whitelisted redirect uri.

Client Credentials

In case a Client needs an OAuth Access Token, the Client Credentials flow allows an OAuth Client to make an authenticated request on the token endpoint to request an Access Token. Authentication is based on the Client Secret. There is no user authenticated in this flow, which makes it suitable for server to server communication only.

The client credentials flow is available on the oauth-token endpoint and is accessed with a POST and the content type application/x-www-form-urlencoded. The following request parameters are supported:

Attribute Required Default value Description
scope No No Scope The scopes, space separated, to include in the token. Must be a subset of the scopes configured on the client.
grant_type Yes None Must be set to client_credentials
client_id No None The client id of the requestor. If not set basic auth must be used
client_secret No None The secret of the client. If not set, basic auth must be used

Resource Owner Password Credentials

Mainly for supporting legacy applications, the Resource Owner Password Credentials flow allows an OAuth Client to provide the Resource Owner’s password credentials to the Authorization Server. The AS authenticates both the RO as well as the Client, and issues an OAuth Access Token on success. This flow has the undesired effect that the RO’s credentials are exposed to the OAuth Client.

The resource owner password credentials flow is available on the oauth-token endpoint and is accessed with a POST and the content type application/x-www-form-urlencoded. The following request parameters are supported:

Attribute Required Default value Description
scope No No Scope The scopes, space separated, to include in the token. Must be a subset of the scopes configured on the client.
grant_type Yes None Must be set to password
username Yes None The username of the user to authenticate
password Yes None The password of the user to authenticate
client_id No None The client id of the requestor. If not set basic auth must be used
client_secret No None The secret of the client. If not set, basic auth must be used

OpenID Connect Hybrid Flows

OpenID Connect defines hybrid flows which consists of combinations of (some of) the regular OAuth2 / OpenID Connect flows. To allow this, no extra configuration is needed other than having OpenID Connect enabled on the profile as well as the openid scope granted (and requested) for the client.

As an example, a grant_type could with a hybrid flow allow both code, token and even id_token to be asked for in the same request. This allows for some interesting, albeit not too common, flows for clients that need some data delivered on the front end channel, while still having the capability to retrieve other information from the backend (i.e. can keep a secret). See Hybrid Capabilities on the clients configuration page for more info.

Attribute Required Default value Description
scope Yes No Scope The scopes to include in the token. Must include openid for hybrid flow. Must be a subset of the scopes configured on the client.
state No No State The state will be returned in the final redirect
response_type Yes None Any combination of token, code and id_token.
client_id Yes None The client id of the requestor.
redirect_uri Yes   For OpenID Connect flows, the redirect_uri is always required.
nonce Maybe None Required for id_token. Will be visible in the ID token claims.

Token Exchange

The token exchange flow is a non-standard flow, that a Client can use to exchange an existing Access Token for a new Access Token. This new Access Token’s properties are limited to the original Access Token’s properties.

The purpose is to create a token that is a subset of the original token. Thus the new token cannot contain more authorization than the original token. This operation is typically referred to as downscoping. Two things can be downscoped:

  • Audience
  • Scopes

Thus, the token returned from the endpoint contains fewer audiences and fewer scopes than the original token.

The client needs to have the token-exchange capability enabled to be allowed to use this flow, and the client needs to authenticate (i.e. using Client Authentication).

Token exchange is initiated by the Client making a call to the oauth-token endpoint of the OAuth profile, using the grant_type https://curity.se/grant/accesstoken.

The request is a POST to the oauth-token endpoint with the content type application/x-www-form-urlencoded. The following request parameters are supported:

Attribute Required Default value Description
scope Yes None The scopes, space separated, to include in the token. Must be a subset of the scopes configured on the client.
audience No Unchanged The audiences, space separated, to remove from the token
grant_type Yes None Must be set to https://curity.se/grant/accesstoken
token Yes None The token to downscope
client_id No None The client id of the requestor. If not set basic auth must be used
client_secret No None The secret of the client. If not set, basic auth must be used.

The token exchange flow is available on the oauth-token endpoint.

Important

The grant-type to use for the token exchange flow is https://curity.se/grant/accesstoken

Assisted Token

The assisted token flow is a non-standard flow that a client can use to setup a new Access Token. This flow is particularly well suited to integrate in client side web applications, and is aimed to make integrating token setup as easy as possible.

The client needs to have the assisted-token capability enabled to be allowed to use this flow.

The assisted token flow is available on the oauth-assisted-token endpoint. For more information about the assisted flow see the assisted token api.

Refresh

The refresh flow is used to exchange a refresh token for a new access token and refresh token pair. If reuse-refresh-token is set in the authorization server configuration, only an access token will be returned.

The refresh token flow is available on the oauth-token endpoint and is accessed with a POST and the content type application/x-www-form-urlencoded. The following request parameters are supported:

Attribute Required Default value Description
scope No Unchanged The scopes, space separated, to include in the token
grant_type Yes None Must be set to refresh_token
refresh_token Yes None The refresh token
client_id No None The client id of the requestor. If not set basic auth must be used
client_secret No None The secret of the client. If not set, basic auth must be used.

Tip

If a token with fewer scopes than the original access token is desired, the scope parameter can be used to tell the authorization server which scopes to include. Only scopes available in the original token are allowed to request.

Revoke

The revoke flow is used to revoke an access token or a refresh token.

The revoke flow is available on the oauth-revoke endpoint and is accessed with a POST and the content type application/x-www-form-urlencoded. The following request parameters are supported:

Attribute Required Default value Description
token Yes None The token to revoke
token_type_hint No None Can be set to access_token or refresh_token
token_value_hint No None Can be set to id if the JTI of a JWT is sent instead of the actual JWT.
client_id No None The client id of the requestor. If not set basic auth must be used
client_secret No None The secret of the client. If not set, basic auth must be used.

Introspect

The introspect flow is used to inspect a token, to see if it’s valid and to retrieve the associated data with that token.

The introspection flow is available on the oauth-introspect endpoint and is accessed with a POST and the content type application/x-www-form-urlencoded. The following request parameters are supported:

Attribute Required Default value Description
token Yes None The token to introspect
token_type_hint No None Can be set to access_token or refresh_token
token_value_hint No None Can be set to id if the JTI of a JWT is sent instead of the actual JWT. Note, this only works if the JWT is backed by a datastore.
client_id No None The client id of the requestor. If not set basic auth must be used
client_secret No None The secret of the client. If not set, basic auth must be used.

Json Web Key Set (JWKS)

The JSON Web Key Set endpoint publication of the currently active public keys. These can then be retrieved by the client to use when validating JWTs issued by this token server.

The JWKS is available on the oauth-anonymous endpoint and is unauthenticated. It expects the accept header application/json.

The oauth-anonymous endpoint can publish many services, and the JWKS service is located under <configured_path_of_anonymous>/jwks

Tip

If the oauth-anonymous endpoint is configured with path /oauth/v2/info then the JWKS service is published at /oauth/v2/info/jwks.

Device Flow

The device flow is specified for internet connected devices that have a limited user interface, but need an Access Token or ID token. The device flow allows a device to offload the user interaction that is needed for user authentication and consent to a device of the user’s choice. The result of going through the Device Flow is still an Access Token and/or an ID token, making it possible for the device to operate as a fully enabled OAuth client.

The device flow is initiated by the device, that makes an authenticated back-channel request to the device authorization endpoint. In response to this request, Curity returns a device_code and a user_code to the device, together with a verification_uri that can be used by the user to verify the user_code. It is up to the device to instruct the user to visit the verification_uri.

The process of verifying the user_code is done in three steps:

  1. The user enters the user_code, giving Curity the opportunity to find the context that needs to be verified
  2. The user authenticates, using the device client’s settings
  3. The user is asked to confirm the access that device is requesting

While the user is verifying the user_code, the device can poll the token-endpoint to find out whether verification has completed. Once the user has confirmed access (step 3 above), the response of the device making a request to the oauth-token endpoint will be successful and include the requested token or tokens.

A more detailed description of how the device flow works in Curity can be found in Using the device flow.

Assertion Flow

The flow where the token endpoint can accept an assertion as authorization grant is referred to as the Assertion Flow. Using JWTs as assertions is specified in the JSON Web Token (JWT) Profile for OAuth, published as RFC7523.

To present a JWT as authorization grant, make a POST-request to the token endpoint that uses the value urn:ietf:params:oauth:grant-type:jwt-bearer for the grant_type-parameter, and provide the JWT through the assertion parameter.

A JWT used as assertion is commonly issued by the client that presents it. This is indicated by using the client id as value for the iss-claim of the JWT. In case a particular client must be able to present a JWT that was issued by another entity, the value to expect for the iss claim can be configured through that particular client’s settings.

If a JWT is presented as authorization grant, it needs to include a minimal set of claims, as specified in RFC7523:

Claim Description
iss identity of the entity that issued the JWT; defaults to the client_id value of the client that presents the JWT
sub name of the subject for which the token is requested
aud the receiver of the token, which should be the configured token endpoint in Curity
exp time until when the JWT may be used, in seconds since epoch. Curity will consider a configurable clock skew when this is being evaluated
jti unique identifier of the JWT token

When included in the JWT, Curity considers the nbf (not-before) and iat (issued-at) claims to control the time window in which the token is valid.

Token reuse

By default, Curity ensures that a token used as assertion grant can only be used once. This restriction can be overridden for individual clients by configuring the Assertion Grant settings of that particular client.