- Tokens
-
Access Tokens
- Enabling single access token per subject
- Enabling JWT-based access tokens
- How to add extra properties to an access token
- Getting a list of issued access tokens
- Issuing two access tokens through hybrid flow
- Refresh Tokens
- ID Tokens
- Proof-of-Possession (PoP) Tokens
-
Grant Type
- Scopes
- PKCE (RFC 7636)
- Client Management
- Authorization Requests
- User Authentication
- Error Handling
- Client Authentication
- Introspection
- Userinfo Endpoint
- JARM
- Device Flow (RFC 8628)
Issuing two access tokens through hybrid flow
Preface
You can use OpenID Connect's "Hybrid" flows to issue two access tokens for a client through a single authorization flow.
This article describes a use case of issuing access tokens with restricted scopes and/or a shortened duration, and how Authlete processes it.
Use case
The hybrid flows are useful for authorization server to issue access tokens for a client that consists of a native application (e.g. mobile app) and an web server application (e.g. app backend), with a single authorization request.
A native application is often a public client, whose security risk is higher than a confidential client such as an web server application. In order to mitigate the risk, the hybrid flows can issue an access token for each side and restrict scopes (subsetting) of the particular token for the native application.
Furthermore, for an web server application that makes requests to high-stakes APIs, the flows allow authorization servers to issue access tokens with a shortened duration.
How it works using Authlete
Authlete supports the hybrid flows. For example, its /auth/authorization/issue API can handle an authorization request with “response_type=code token” and create an authorization response including an authorization code and an access token. Also, its /auth/token API accepts a token request including the authorization code and creates a token response including another access token.
Authlete's token updating API (/auth/token/update API) allows authorization servers to modify properties of access tokens, such as scopes, duration. These modifications are applied to access tokens stored in Authlete.
On receiving such access tokens from clients, resource servers will check status and details of the tokens, using Authlete's introspection API (/auth/introspection) and obtain the information modified in the previous step.

Examples
This section describes examples where an authorization server issues two access tokens on receiving an authorization request with “response_type=code token” and modifies scopes and duration for each of the tokens.

Obtaining an access token to be sent back in an authorization response
On receiving an authorization request from a client (via a user agent), an authorization server typically does the following processes.
- Send content of the authorization request to Authlete's /auth/authorization API (step #2, #3)
- Authenticate an end user and ask consent (step #4, #5)
- Make a request to /auth/authorization/issue API and obtain content of an authorization response (step #6, #7)
The following example is a response from /auth/authorization/issue API (step #7). It contains an access token as a value of "accessToken", to be provided from the authorization server's authorization endpoint to the client. Content of "responseContent" indicates that the token has scope=openid profile payment. (all examples below are folded for readability)
{ "type": "authorizationIssueResponse", "resultCode": "A040001", "resultMessage": "[A040001] The authorization request was processed successfully.", "accessToken": "stm3IfTHV_F1iVKEYQBJA58XMzA7OQ59-MQpdM3NH6c", "accessTokenDuration": 1800, "accessTokenExpiresAt": 1596379999493, "action": "LOCATION", "authorizationCode": "iEATjO9V24Rubj1_PnATziCGh4ivVPRcTK_VZOsGplI", "responseContent": "https://client.example.org/cb/example.com #code=iEATjO9V24Rubj1_PnATziCGh4ivVPRcTK_VZOsGplI &access_token=stm3IfTHV_F1iVKEYQBJA58XMzA7OQ59-MQpdM3NH6c &token_type=Bearer &expires_in=1800 &scope=openid+profile+payment" }
Narrowing (subsetting) scopes
The access token has three scopes: openid, profile and payment. The authorization server modifies the granted scopes (removes unnecessary scopes) using Authlete's /auth/token/update API (step #6, #7). In this example, the server removes “payment” scope and preserves “openid” and “profile.”
- Request (step #6 using curl command)
curl -s -X POST $apiUrl/auth/token/update -u $apiKey:$apiSecret -H 'Content-type: application/json' -d '{"accessToken":"stm3IfTHV_F1iVKEYQBJA58XMzA7OQ59-MQpdM3NH6c", "scopes":["openid","profile"]}'
- Response (step #7)
{ "type": "tokenUpdateResponse", "resultCode": "A135001", "resultMessage": "[A135001] Updated the access token successfully.", "accessToken": "stm3IfTHV_F1iVKEYQBJA58XMzA7OQ59-MQpdM3NH6c", "accessTokenExpiresAt": 1596379999000, "action": "OK", "scopes": [ "openid", "profile" ], "tokenType": "Bearer" }
The authorization server will send back the content of "responseContent", obtained from a response of /auth/authorization/issue API as shown above, to the client (step #8).
Obtaining an access token to be sent back in a token response
On receiving a token request from a client (step #13), an authorization server typically does the following process.
- Send content of the token request to Authlete's /auth/token API (step #14, #15)
The following example is a response from /auth/token API (step #15). It contains an access token as a value of "accessToken", to be provided from the authorization server's token endpoint to the client. A value of "accessTokenExpiresAt" indicates that the token is to be expired on 1596380052227 (in Unix time).
{ "type": "tokenResponse", "resultCode": "A050001", "resultMessage": "[A050001] The token request (grant_type=authorization_code) was processed successfully.", "accessToken": "zcxCRPL3P1n7gUnn1gnRAz3nndUdYeyilpU7txGE3gg", "accessTokenDuration": 1800, "accessTokenExpiresAt": 1596380052227, "action": "OK", "clientId": 17201083166161, "clientIdAlias": "clientapp01", "clientIdAliasUsed": false, "grantType": "AUTHORIZATION_CODE", "idToken": "eyJhbGciOiJIUzI1NiJ9. eyJzdWIiOiJ0ZXN0dXNlcjAxIiwiYXVkIjpbIjE3MjAxMDgzMTY2MTYxIl0s ImlzcyI6Imh0dHBzOi8vYXV0aGxldGUuY29tIiwiZXhwIjoxNTk2NDY0NjUy LCJpYXQiOjE1OTYzNzgyNTJ9. uJiJxISW7d0HEgOyQsIFbqptOREeqs9zJYMs_ZhZ72w", "refreshToken": "98YoC89H9CYcc56amo0bvNZ8pV02dYZmxCvB0Wz31jU", "refreshTokenDuration": 9000, "refreshTokenExpiresAt": 1596387252227, "responseContent": "{\"access_token\":\"zcxCRPL3P1n7gUnn1gnRAz3nndUdYeyilpU7txGE3gg\", \"refresh_token\":\"98YoC89H9CYcc56amo0bvNZ8pV02dYZmxCvB0Wz31jU\", \"scope\":\"openid profile payment\", \"id_token\": \"eyJhbGciOiJIUzI1NiJ9. eyJzdWIiOiJ0ZXN0dXNlcjAxIiwiYXVkIjpbIjE3MjAxMDgzMTY2MTYxIl0s ImlzcyI6Imh0dHBzOi8vYXV0aGxldGUuY29tIiwiZXhwIjoxNTk2NDY0NjUy LCJpYXQiOjE1OTYzNzgyNTJ9. uJiJxISW7d0HEgOyQsIFbqptOREeqs9zJYMs_ZhZ72w\", \"token_type\":\"Bearer\", \"expires_in\":1800}", "scopes": [ "openid", "profile", "payment" ], "subject": "testuser01" }
Shortening a duration
In the same way as the previous example, the authorization server modifies the duration of the access token using Authlete's /auth/token/update API (step #16, #17). In this example, it specifies 1596379152000, that means 900 seconds (900,000 milliseconds) shorter than the original duration.
- Request (Step #16 using curl command)
curl -s -X POST $apiUrl/auth/token/update -u $apiKey:$apiSecret -H 'Content-type: application/json' -d '{"accessToken":"zcxCRPL3P1n7gUnn1gnRAz3nndUdYeyilpU7txGE3gg", "accessTokenExpiresAt":1596379152000}'
- Response (step #17)
{ "type": "tokenUpdateResponse", "resultCode": "A135001", "resultMessage": "[A135001] Updated the access token successfully.", "accessToken": "zcxCRPL3P1n7gUnn1gnRAz3nndUdYeyilpU7txGE3gg", "accessTokenExpiresAt": 1596379152000, "action": "OK", "scopes": [ "openid", "profile", "payment" ], "tokenType": "Bearer" }
How did we do with this article?