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.
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.
oauth-authorize
oauth-token
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:
code
openid
plain
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.
application/x-www-form-urlencoded
POST request parameters
authorization_code
code_challenge
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.
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:
token
The response is given as a fragment parameter in a redirect back to the client on a predefined or whitelisted redirect uri.
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:
client_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:
password
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.
hybrid
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.
grant_type
id_token
Client Initiated Backchannel Authentication (CIBA) is an OpenID Connect authentication flow in which Relying Parties (RP), that can obtain a valid identifier for the user they want to authenticate, will be able to initiate an interaction flow to authenticate their users without having end-user interaction from the consumption device.
In order to be able to use back-channel authentication, an endpoint of type oauth-backchannel-authentication needs to be configured in the Token Service profile.
oauth-backchannel-authentication
Token Service
Back-channel Authenticators of supported types needs to be created in Authentication profile under the Back-channel Authenticators section of the admin UI. Depending on the authenticator type, the back-channel authenticator can have its own settings or optionally link to a front-channel authenticator in the same plugin group to re-use its settings and managed objects.
Authentication
Back-channel Authenticators
If multiple back-channel authenticators are configured, then back-channel authentication will be attempted on all of them for a request to start back-channel authentication. If required, it can be limited by specifying acr_values in the request.
acr_values
Back-channel authentication can be enabled or disabled using admin UI under Capabilities section of Client Settings in Token Service profile. In addition, the following settings can also be configured.
Capabilities
Client Settings
requested_expiry
Request Object JWT
Signature Verification Key
Authentication can be initiated by the client by making a HTTP POST request to the configured back-channel endpoint with the below parameters. Upon successful initiation, the response would contain auth_req_id that corresponds to the CIBA Authentication request. Any additional parameters provided will be ignored by the server for the authentication request, however they are available for inspection in back-channel token procedure and can be included in the tokens, if required.
HTTP POST
auth_req_id
Currently, the Curity Identity Server supports only poll mode to get authentication result as specified in section 5 of the CIBA spec. The token can be obtained by making a poll request to the token endpoint using HTTP POST with below parameters. The poll request may be repeated until success or error for a period mentioned as expires_in in the initiation response at an interval specified by interval value.
poll
expires_in
interval
urn:openid:params:grant-type:ciba
A signed authentication request can be made by encoding all of the authentication request parameters as claims of a signed JWT with each parameter name as the claim name and its value as a JSON string. The JWT must contain all of the authentication request parameters and be signed with asymmetric signing algorithm. The signed authentication request JWT should be passed as an application/x-www-form-urlencoded HTTP request parameter with the name request. The signing key for signed requests, is either statically configured as request-object configuration for a client, or taken from the jwks_uri in case of a dynamically registered client.
request
jwks_uri
The OAuth 2.0 Token Exchange is a standardized token exchange flow for service to service impersonation, and AS to AS token conversion. It is specified in RFC 8693 and defines multiple ways to exchange tokens.
Token exchange is initiated by the Client making a call to the oauth-token endpoint of the OAuth profile, using the grant_type urn:ietf:params:oauth:grant-type:token-exchange.
urn:ietf:params:oauth:grant-type:token-exchange
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:
actor_token
urn:ietf:params:oauth:token-type:access_token
access_token
The OAuth 2.0 Token Exchange grant in the Curity Identity Server is highly customizable, this is due to the inherent properties of the flow itself. It can be used for many purposes many of which are custom and use-case specific. The flow is therefore structured to be customized in token procedures or token procedure plugins. If no plugin or procedure is configured the default procedure will execute.
The default procedure supports three different behaviours:
Convert an opaque access token to an access token in JWT format Reduce the scopes (downscope) of an access token, returning a token with fewer scopes Reduce the audiences (downaudience) an access token, returning a token with fewer audiences
Functions 2 and 3 can be combined in a single request, both downscoping and downaudiencing the token.
1. Convert an opaque access token to an access token in JWT format
To convert an opaque token to a JWT access token (i.e. the phantom token flow) the following parameters should be sent to the token endpoint:
urn:ietf:params:oauth:token-type:jwt
No other parameters may be used.
2 or 3: Downscope or downaudience a token
This converts a token issued by the same token profile in the Curity Identity Server to a new access token with the same expiration, but with fewer scopes and/or audiences.
subject_token
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:
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.
https://curity.se/grant/accesstoken
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
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.
oauth-assisted-token
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 or client configuration, only an access token will be returned.
reuse-refresh-token
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:
refresh_token
The time validity of refresh tokens is defined by two configuration settings:
refresh-token-ttl
disabled
refresh-token-max-rolling-lifetime
Using the refresh token flow, a client can obtain fresh access tokens and refresh tokens, until refresh-token-max-rolling-lifetime has elapsed since the first token request, as long as each refresh token is used before refresh-token-ttl seconds since its issuance.
Both these settings are configurable:
The default values configured for the non-templatized dynamic clients can be overriden during dynamic client registration or dynamic client management via two custom registration parameters:
refresh_token_ttl
refresh_token_max_rolling_lifetime
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.
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:
oauth-revoke
id
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:
oauth-introspect
The Curity Identity Server can also respond to requests in the introspection endpoint with the Accept: application/jwt header. When introspecting a valid access token, the Curity Identity Server responds with 200 OK and the JWT in the body of the response. An expired or invalid access token, causes the Curity Identity Server to respond with 204 No Content.
Accept: application/jwt
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.
oauth-anonymous
application/json
The oauth-anonymous endpoint can publish many services, and the JWKS service is located under <configured_path_of_anonymous>/jwks
If the oauth-anonymous endpoint is configured with path /oauth/v2/info then the JWKS service is published at /oauth/v2/info/jwks.
/oauth/v2/info
/oauth/v2/info/jwks
The device flow (Device Authorization Grant) 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.
device authorization
device_code
user_code
verification_uri
The process of verifying the user_code is done in three steps:
The user enters the user_code, giving Curity the opportunity to find the context that needs to be verified The user authenticates, using the device client’s settings 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.
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.
urn:ietf:params:oauth:grant-type:jwt-bearer
assertion
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.
iss
If a JWT is presented as authorization grant, it needs to include a minimal set of claims, as specified in RFC7523:
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.
nbf
iat
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.
When a client wants to indicate to the Token Service that a user is logged out, it can call the logout path on the Session endpoint (i.e. the end_session_endpoint in the Metadata). Doing so will log the user out of the associated Authentication Service, as well as notify all clients that the user has logged in to through their respective registered frontchannel- or backchannel logout uri’s, so called Single Logout.
end_session_endpoint
Logout follows the OpenId Connect Session Management, OpenId Connect Backchannel Logout and OpenId Connect Frontchannel logout specifications.
More details are in Session Management and Logout.