Skip to content

Authorization Code Redemption

Dick Davis edited this page Jan 23, 2026 · 3 revisions

Authorization Code Redemption

Authorization code redemption is the process by which a client redeems a previously issued authorization code in exchange for access and refresh tokens.

Process

---
title: Authorization Code Redemption
---
sequenceDiagram
autonumber

actor Client
participant Authorization Service
participant Data Layer

Client-->>Authorization Service: Calls the token endpoint with authorization code and code verifier
Note right of Client: POST /oauth/token
Authorization Service-->>Data Layer: Retrieves authorization code and code challenge
Authorization Service-->Authorization Service: Verifies code verifier with code challenge
Authorization Service-->Authorization Service: Generates access and refresh tokens
Authorization Service-->>Data Layer: Creates an OAuth Session record with token JTI's
Authorization Service-->>Client: Returns access and refresh tokens to client
Loading

Client

The Client entity represents a client application registered with the OAuth provider.

Authorization Service

The Authorization Service entity represents the component of the application which is responsible for redeeming the authorization code and issuing access and refresh tokens. This is provided by TokenAuthority.

Data Layer

The Data Layer entity is a relational database used for storing data related to authorization grants and OAuth sessions.

Endpoints

POST /oauth/token

The client calls the POST /oauth/token endpoint to redeem an authorization code for access and refresh tokens. The endpoint responds with either an error code conforming to RFC-6749 or a JSON object containing the access and refresh tokens.

HTTP Method: POST

URL: /oauth/token

Content-Type: application/x-www-form-urlencoded

Params:

Param Required? Description
grant_type yes The authorization grant type for the authorization code grant process. Must be authorization_code.
code yes The authorization code previously issued to the client during the authorization process.
code_verifier yes (public clients) The code verifier used to generate the code challenge provided during the authorization process.
redirect_uri yes (public clients) The redirect URI that was used in the authorization request. Must match exactly.
client_id no The client identifier. Required for public clients if not already authenticated.
scope no Space-separated list of scope tokens. Must be a subset of scopes granted during authorization.
resource no Target resource URI(s) for the access token (RFC 8707). Must be a subset of resources granted during authorization. Can be repeated for multiple resources.

Example Request:

POST /oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&
code=02a456ce-73a5-416d-8159-7c8bff9a19e5&
code_verifier=CR70DhqQkvzPL2JjlQNyiCNgoRDZj2jko0mW7CpEUXJPgK-uEeQoZCSJlBgup73MtqpdeYRLmA&
redirect_uri=http://localhost:8080/callback

Example Request with Scope Downscoping:

POST /oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&
code=02a456ce-73a5-416d-8159-7c8bff9a19e5&
code_verifier=CR70DhqQkvzPL2JjlQNyiCNgoRDZj2jko0mW7CpEUXJPgK-uEeQoZCSJlBgup73MtqpdeYRLmA&
redirect_uri=http://localhost:8080/callback&
scope=read

Example Request with Resource Indicators (RFC 8707):

POST /oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&
code=02a456ce-73a5-416d-8159-7c8bff9a19e5&
code_verifier=CR70DhqQkvzPL2JjlQNyiCNgoRDZj2jko0mW7CpEUXJPgK-uEeQoZCSJlBgup73MtqpdeYRLmA&
redirect_uri=http://localhost:8080/callback&
resource=https://api.example.com/

Example Response:

{
    "access_token": "eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjMwMDAvYXBpLyIsImlhdCI6MTY5NTE0MDY1NiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDozMDAwLyIsImp0aSI6Ijc0YjVkZTlkLTQ4YmQtNDFjNC1hMGNiLWZjYzM0OWU3MTY2NyIsInVzZXJfaWQiOjMsImV4cCI6MTY5NTE0MDk1Nn0.aUhztv6x2-foSfp17W_7-mMC-w3HKUx25pMSWHYjzqY",
    "refresh_token": "eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjMwMDAvYXBpLyIsImlhdCI6MTY5NTE0MDY1NiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDozMDAwLyIsImp0aSI6IjUxMGJhNTdiLTgwNTQtNGQxYi1iYWQ1LTVmZmZjOWE0NzA4ZCIsImV4cCI6MTY5NjM1MDI1Nn0.6-7DgP4UFcA7hEkK7XRob_sRNEGH1QlvalysDJjBrko",
    "token_type": "bearer",
    "expires_in": 300
}

Response Fields:

Field Description
access_token A JWT access token for authenticating API requests.
refresh_token A JWT refresh token for obtaining new access tokens.
token_type The token type. Always bearer.
expires_in The number of seconds until the access token expires.
scope Space-separated list of scopes granted (only included if scopes were requested).

Error Response:

{
    "error": "invalid_grant"
}

Common error codes:

  • invalid_grant - The authorization code is invalid or has already been redeemed.
  • invalid_request - The request is missing required parameters or the code verifier is invalid.
  • invalid_scope - The requested scope is invalid or was not granted during authorization.
  • invalid_target - The requested resource is invalid or was not granted during authorization (RFC 8707).

Scope in Access Tokens

When scopes are requested (either during authorization or at token exchange), the access token's scope claim contains the space-delimited scope tokens. The token response also includes a scope field echoing the granted scopes.

Resource servers should validate that required scopes are present in the token's scope claim before allowing access to protected resources.

Scope Downscoping

At token exchange, clients can request a subset of the scopes that were granted during authorization. This allows obtaining tokens with minimal necessary permissions:

# During authorization, user granted read and write scopes
scope=read write

# At token exchange, client only needs read access
scope=read

If no scope parameter is provided at token exchange, the token is issued with all scopes granted during authorization.

Audience Binding (RFC 8707)

When resources are requested (either during authorization or at token exchange), the access token's aud claim is set to the requested resource URI(s):

  • Single resource: aud is a string containing the resource URI
  • Multiple resources: aud is an array of resource URIs

Resource servers should validate that their URI is present in the aud claim before accepting the token.

Resource Downscoping

At token exchange, clients can request a subset of the resources that were granted during authorization. This allows obtaining tokens with minimal necessary permissions:

# During authorization, user granted access to both APIs
resource=https://api.example.com/&resource=https://billing.example.com/

# At token exchange, client only needs the main API
resource=https://api.example.com/

If no resource parameter is provided at token exchange, the token is issued for all resources granted during authorization.

References

Clone this wiki locally