> ## Documentation Index
> Fetch the complete documentation index at: https://developers.authlete.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Supporting FAPI 2.0 Message Signing Profile: Signing Authorization Responses with Authlete

> Supporting FAPI 2.0 Message Signing Profile: Signing Authorization Responses with Authlete.

<Note>
  This page is for **Authlete 3.x**. For 2.x documentation, see [this page](/v2/protocols-and-flows/compliance-profiles/supporting-fapi-2-0-message-signing-profile-signing-authorization-responses).
</Note>

## Overview

This article explains how to support [FAPI 2.0 Message Signing Profile: Signing Authorization Responses](https://openid.net/specs/fapi-message-signing-2_0-final.html#section-5.4) (hereinafter referred to as FAPI2 authorization response signing) and in Authlete.

<Note>
  "FAPI2 authorization response signing" is available since Authlete 2.3.
</Note>

<Note>
  "FAPI2 authorization response signing” requires satisfying all requirements of FAPI 2.0 Security Profile.
</Note>

## Preconditions

* This document uses Authorization Code Flow compliant with FAPI2 authorization response signing as an example.
* `private_key_jwt` is used for client authentication.
* DPoP is used for sender-constrained access tokens.

<img src="https://mintcdn.com/authlete/oZd1VUaYFwHO2MBx/protocols-and-flows/compliance-profiles/authz-code-flow.png?fit=max&auto=format&n=oZd1VUaYFwHO2MBx&q=85&s=1bef634bd20318f0974248127ed01326" width="2880" height="1620" data-path="protocols-and-flows/compliance-profiles/authz-code-flow.png" />

## Service Settings

Configure your service as follows.

### ☑️ Basic Settings > Issuer Identifier

<img src="https://mintcdn.com/authlete/UdhsyS8JFpC2EXja/protocols-and-flows/compliance-profiles/v30-service-issuer-identifier.png?fit=max&auto=format&n=UdhsyS8JFpC2EXja&q=85&s=868badba7efb75df0e108a4e9c3817ac" width="2122" height="342" data-path="protocols-and-flows/compliance-profiles/v30-service-issuer-identifier.png" />

Set the authorization server's issuer identifier.

### ☑️ Basic Settings > FAPI Profile

<img src="https://mintcdn.com/authlete/pc0lPZhy9Zo_eIBR/protocols-and-flows/compliance-profiles/v30-service-fapi-profile.png?fit=max&auto=format&n=pc0lPZhy9Zo_eIBR&q=85&s=dc5edb367f7cfd42d67b0f23207f237e" width="2126" height="316" data-path="protocols-and-flows/compliance-profiles/v30-service-fapi-profile.png" />

Enable this setting.

### ☑️ Endpoints > Global Settings > Supported Grant Types

<img src="https://mintcdn.com/authlete/UdhsyS8JFpC2EXja/protocols-and-flows/compliance-profiles/v30-service-supported-grant-types.png?fit=max&auto=format&n=UdhsyS8JFpC2EXja&q=85&s=61e08d717b1c625c36180cd3480b5cdd" width="2112" height="768" data-path="protocols-and-flows/compliance-profiles/v30-service-supported-grant-types.png" />

Include `AUTHORIZATION_CODE`.

### ☑️ Endpoints > Global Settings > Supported Response Types

<img src="https://mintcdn.com/authlete/UdhsyS8JFpC2EXja/protocols-and-flows/compliance-profiles/v30-service-supported-response-types.png?fit=max&auto=format&n=UdhsyS8JFpC2EXja&q=85&s=77c461df1ce3af81c036da3d41b675f0" width="2110" height="690" data-path="protocols-and-flows/compliance-profiles/v30-service-supported-response-types.png" />

Include `CODE`.

### ☑️ Endpoints > Authorization > Authorization Endpoint URL

<img src="https://mintcdn.com/authlete/pc0lPZhy9Zo_eIBR/protocols-and-flows/compliance-profiles/v30-service-authorization-endpoint-url.png?fit=max&auto=format&n=pc0lPZhy9Zo_eIBR&q=85&s=5bdeb32c89e5a1d5d8a981d912e52055" width="2116" height="300" data-path="protocols-and-flows/compliance-profiles/v30-service-authorization-endpoint-url.png" />

Set the authorization endpoint URL.

### ☑️ Endpoints > Authorization > Issuer Identification Response Parameter

<img src="https://mintcdn.com/authlete/UdhsyS8JFpC2EXja/protocols-and-flows/compliance-profiles/v30-service-issuer-identification-response-parameter.png?fit=max&auto=format&n=UdhsyS8JFpC2EXja&q=85&s=ce9ae0863e729d66526538bc8a3d425c" width="2118" height="314" data-path="protocols-and-flows/compliance-profiles/v30-service-issuer-identification-response-parameter.png" />

Disable this setting.

> "FAPI 2.0 Security Profile, 5.3.2. Requirements for authorization servers, 5.3.2.2. Authorization endpoint flows"

7. shall return an `iss` parameter in the authorization response according to \[RFC9207];

### ☑️ Endpoints > Authorization > Loopback Redirection URI

<img src="https://mintcdn.com/authlete/UdhsyS8JFpC2EXja/protocols-and-flows/compliance-profiles/v30-service-loopback-redirection-uri.png?fit=max&auto=format&n=UdhsyS8JFpC2EXja&q=85&s=a9c713b7b338ecc5a3cd762becbc94f4" width="2114" height="310" data-path="protocols-and-flows/compliance-profiles/v30-service-loopback-redirection-uri.png" />

Enable this setting.

> "FAPI 2.0 Security Profile, 5.3.2. Requirements for authorization servers, 5.3.2.2. Authorization endpoint flows"

8. shall not transmit authorization responses over unencrypted network connections, and, to this end, shall not allow redirect URIs that use the "http" scheme except for native clients that use loopback interface Redirection as described in Section 7.3 of \[RFC8252];

### ☑️ Endpoints > Token > Token Endpoint URI

<img src="https://mintcdn.com/authlete/UdhsyS8JFpC2EXja/protocols-and-flows/compliance-profiles/v30-service-token-endpoint-url.png?fit=max&auto=format&n=UdhsyS8JFpC2EXja&q=85&s=ff1a86a178f3840f01597a1ee6e476fd" width="2116" height="298" data-path="protocols-and-flows/compliance-profiles/v30-service-token-endpoint-url.png" />

Set the token endpoint URI.

### ☑️ Endpoints > Token > Supported Client Authentication Methods

<img src="https://mintcdn.com/authlete/UdhsyS8JFpC2EXja/protocols-and-flows/compliance-profiles/v30-service-supported-client-authentication-methods.png?fit=max&auto=format&n=UdhsyS8JFpC2EXja&q=85&s=6cb39c39482d6f2abb86fcda0ce12ba7" width="2112" height="696" data-path="protocols-and-flows/compliance-profiles/v30-service-supported-client-authentication-methods.png" />

Include `PRIVATE_KEY_JWT`.

> "FAPI 2.0 Security Profile, 5.3.2. Requirements for authorization servers, 5.3.2.1. General requirements"

6. shall authenticate clients using one of the following methods:

>

* MTLS as specified in Section 2 of \[RFC8705], or

>

* `private_key_jwt` as specified in Section 9 of \[OIDC];

### ☑️ Endpoints > Token > Assertion Audience Mode

<img src="https://mintcdn.com/authlete/pc0lPZhy9Zo_eIBR/protocols-and-flows/compliance-profiles/v30-service-assertion-audience-mode.png?fit=max&auto=format&n=pc0lPZhy9Zo_eIBR&q=85&s=6350723a852c471da07f0f1d80d643e0" width="2112" height="312" data-path="protocols-and-flows/compliance-profiles/v30-service-assertion-audience-mode.png" />

Enable this setting.

> "FAPI 2.0 Security Profile, 5.3.2. Requirements for authorization servers, 5.3.2.1. General requirements"

8. shall only accept its issuer identifier value (as defined in \[RFC8414]) as a string in the aud claim received in client authentication assertions;

### ☑️ Endpoints > General > Pushed Authorization Request (PAR)

<img src="https://mintcdn.com/authlete/UdhsyS8JFpC2EXja/protocols-and-flows/compliance-profiles/v30-service-pushed-authorization-request.png?fit=max&auto=format&n=UdhsyS8JFpC2EXja&q=85&s=66b8cc2510d38d2106ecb5f61b0d80b8" width="2114" height="582" data-path="protocols-and-flows/compliance-profiles/v30-service-pushed-authorization-request.png" />

* Set **PAR Endpoint URL**.
* Set **PAR Endpoint Duration** (the expiration time for request URIs). The duration value must be less than 600 seconds.

> "FAPI 2.0 Security Profile, 5.3.2. Requirements for authorization servers, 5.3.2.2. Authorization endpoint flows"

12. shall issue pushed authorization requests request\_uri with expires\_in values of less than 600 seconds;

### ☑️ Tokens and Claims > Refresh Token > Refresh Token Rotation

<img src="https://mintcdn.com/authlete/UdhsyS8JFpC2EXja/protocols-and-flows/compliance-profiles/v30-service-refresh-token-rotation.png?fit=max&auto=format&n=UdhsyS8JFpC2EXja&q=85&s=89b2ebcc07f729024c9b011446bb1491" width="2114" height="696" data-path="protocols-and-flows/compliance-profiles/v30-service-refresh-token-rotation.png" />

Disable Refresh Token Rotation.

> "FAPI 2.0 Security Profile, 5.3.2. Requirements for authorization servers, 5.3.2.1. General requirements"

9. shall not use refresh token rotation except in extraordinary circumstances (see Note 1 below);

> ...
>
> NOTE 1: The use of refresh token rotation does not provide security benefits when used with confidential clients and sender-constrained access tokens. This specification prohibits the use of refresh token rotation for security reasons as it causes user experience degradation and operational issues whenever the client fails to store or receive the new refresh token and has no option to retry.
>
> However, as refresh token rotation may be required from time to time for infrastructure migration or similar extraordinary circumstances, this specification allows it, provided that authorization servers offer clients the time-limited option to retry with the old refresh token in case of failure. Implementers need to consider a secure mechanism for clients to recover from a loss of a new refresh token on issue. The details of this mechanism are outside the scope of this specification.

### ☑️ Tokens and Claims > ID Token

<img src="https://mintcdn.com/authlete/pc0lPZhy9Zo_eIBR/protocols-and-flows/compliance-profiles/v30-service-allowable-clock-skew.png?fit=max&auto=format&n=pc0lPZhy9Zo_eIBR&q=85&s=d59ef2da21a0f443b96daa43f96a6a87" width="2040" height="332" data-path="protocols-and-flows/compliance-profiles/v30-service-allowable-clock-skew.png" />

Set an allowable clock skew value that meets the following condition:

```
10 seconds ≤ clock skew ≤ 60 seconds
```

> "FAPI 2.0 Security Profile, 5.3.2. Requirements for authorization servers, 5.3.2.1. General requirements"

13. to accommodate clock offsets, shall accept JWTs with an iat or nbf timestamp between 0 and 10 seconds in the future but shall reject JWTs with an iat or nbf timestamp greater than 60 seconds in the future. See Note 3 for further details and rationale;

> ...
>
> NOTE 3: Clock skew is a cause of many interoperability issues. Even a few hundred milliseconds of clock skew can cause JWTs to be rejected for being “issued in the future”. The DPoP specification \[RFC9449] suggests that JWTs are accepted in the reasonably near future (on the order of seconds or minutes). This document goes further by requiring authorization servers to accept JWTs that have timestamps up to 10 seconds in the future. 10 seconds was chosen as a value that does not affect security while greatly increasing interoperability. Implementers are free to accept JWTs with a timestamp of up to 60 seconds in the future. Some ecosystems have found that the value of 30 seconds is needed to fully eliminate clock skew issues. To prevent implementations switching off iat and nbf checks completely this document imposes a maximum timestamp in the future of 60 seconds.

### ☑️ Tokens and Claims > Advanced > Supported Scopes

<img src="https://mintcdn.com/authlete/UdhsyS8JFpC2EXja/protocols-and-flows/compliance-profiles/v30-service-supported-scopes.png?fit=max&auto=format&n=UdhsyS8JFpC2EXja&q=85&s=25e35bdb6680ed86ef948ab36c9f0cb6" width="2116" height="634" data-path="protocols-and-flows/compliance-profiles/v30-service-supported-scopes.png" />

<img src="https://mintcdn.com/authlete/UdhsyS8JFpC2EXja/protocols-and-flows/compliance-profiles/v30-service-supported-scopes-create-scope.png?fit=max&auto=format&n=UdhsyS8JFpC2EXja&q=85&s=27652a9ac61f965646157c6af572a53c" width="1074" height="1458" data-path="protocols-and-flows/compliance-profiles/v30-service-supported-scopes-create-scope.png" />

Create a scope named `myscope` and add a scope attribute with the key `fapi2` and the value `ms-authres`.

## Client Configurations

Configure your client as follows.

### ☑️ Basic Settings > Client Type

<img src="https://mintcdn.com/authlete/pc0lPZhy9Zo_eIBR/protocols-and-flows/compliance-profiles/v30-client-client-type.png?fit=max&auto=format&n=pc0lPZhy9Zo_eIBR&q=85&s=cf8dc85582ec56c998f269f9f064005e" width="2124" height="304" data-path="protocols-and-flows/compliance-profiles/v30-client-client-type.png" />

Select `CONFIDENTIAL`.

### ☑️ Endpoints > Global Settings > Supported Grant Types

<img src="https://mintcdn.com/authlete/pc0lPZhy9Zo_eIBR/protocols-and-flows/compliance-profiles/v30-client-supported-grant-types.png?fit=max&auto=format&n=pc0lPZhy9Zo_eIBR&q=85&s=fccf1d52eac11b7ad3ee2db8fb2cc37f" width="2114" height="766" data-path="protocols-and-flows/compliance-profiles/v30-client-supported-grant-types.png" />

Include `AUTHORIZATION_CODE`.

### ☑️ Endpoints > Global Settings > Supported Response Types

<img src="https://mintcdn.com/authlete/pc0lPZhy9Zo_eIBR/protocols-and-flows/compliance-profiles/v30-client-supported-response-types.png?fit=max&auto=format&n=pc0lPZhy9Zo_eIBR&q=85&s=ef6cecbba2e0f522ecf850b9e15d8895" width="2108" height="688" data-path="protocols-and-flows/compliance-profiles/v30-client-supported-response-types.png" />

Include `CODE`.

### ☑️ Endpoints > Global Settings > Redirect URIs

<img src="https://mintcdn.com/authlete/pc0lPZhy9Zo_eIBR/protocols-and-flows/compliance-profiles/v30-client-redirect-uris.png?fit=max&auto=format&n=pc0lPZhy9Zo_eIBR&q=85&s=596cbfdbc1ce8654f294c802325a6b9b" width="2028" height="504" data-path="protocols-and-flows/compliance-profiles/v30-client-redirect-uris.png" />

Register at least one redirect URI starting with `https`.

### ☑️ Endpoints > Token > Client Authentication Method

<img src="https://mintcdn.com/authlete/pc0lPZhy9Zo_eIBR/protocols-and-flows/compliance-profiles/v30-client-client-authentication-method.png?fit=max&auto=format&n=pc0lPZhy9Zo_eIBR&q=85&s=9a63cd9ae7f95bb09558e366d42c315b" width="2106" height="270" data-path="protocols-and-flows/compliance-profiles/v30-client-client-authentication-method.png" />

Select `PRIVATE_KEY_JWT`.

> "FAPI 2.0 Security Profile, 5.3.3. Requirements for clients, 5.3.3.1. General requirements"

2. shall support client authentication using one or both of the following methods:

>

* MTLS as specified in Section 2 of \[RFC8705],

>

* `private_key_jwt` as specified in Section 9 of \[OIDC];

### ☑️ Endpoints > Token > Assertion Signature Algorithm

<img src="https://mintcdn.com/authlete/pc0lPZhy9Zo_eIBR/protocols-and-flows/compliance-profiles/v30-client-assertion-signature-algorithm.png?fit=max&auto=format&n=pc0lPZhy9Zo_eIBR&q=85&s=bc7860186df930ad1955864bf7accc68" width="2112" height="344" data-path="protocols-and-flows/compliance-profiles/v30-client-assertion-signature-algorithm.png" />

Select `ES256`.

> "FAPI 2.0 Security Profile, 5.4. Cryptography and secrets, 5.4.1. General requirements"

1. Authorization servers, clients, and resource servers when creating or processing JWTs shall

> * adhere to \[RFC8725];
> * use `PS256`, `ES256`, or `EdDSA` (using the `Ed25519` variant) algorithms; and
> * not use or accept the none algorithm.

### ☑️ Key Management > JWK Set > JWK Set Content

<img src="https://mintcdn.com/authlete/pc0lPZhy9Zo_eIBR/protocols-and-flows/compliance-profiles/v30-client-jwks.png?fit=max&auto=format&n=pc0lPZhy9Zo_eIBR&q=85&s=ea45b7489bae089207afcf67a3bc7cd6" width="2100" height="606" data-path="protocols-and-flows/compliance-profiles/v30-client-jwks.png" />

Set a JWK set. Since we use `private_key_jwt` for client authentication, the JWK set must include a client assertion signing key. Note that keys contained in the JWK set must satisfy the following requirements.

> "FAPI 2.0 Security Profile, 5.4. Cryptography and secrets, 5.4.1. General requirements"

2. RSA keys shall have a minimum length of 2048 bits.

>

3. Elliptic curve keys shall have a minimum length of 224 bits.

## Demonstration

This section demonstrates Authorization Code Flow in FAPI2 authorization response signing by using Authlete APIs.

### 1. Pushed Authorization Request & Response

<img src="https://mintcdn.com/authlete/U02sYmcLE8xIcCKt/protocols-and-flows/compliance-profiles/par-req-and-res-cropped.png?fit=max&auto=format&n=U02sYmcLE8xIcCKt&q=85&s=d53edada4c72567d3f73b3a051ceddaf" width="2880" height="839" data-path="protocols-and-flows/compliance-profiles/par-req-and-res-cropped.png" />

Suppose that a client that implements FAPI2 authorization response signing sends a valid request to the pushed authorization request endpoint of the authorization server. The client and the request should meet the following requirements.

### ☑️ Client Authentication

The client uses `private_key_jwt` for client authentication at the pushed authentication request endpoint (as configured above).

### ☑️ Scope

The `scope` request parameter includes `myscope`, which is linked to an attribute `fapi2=ms-authres` as configured above.

### ☑️ Response Type

The `response_type` request parameter is set to `code`.

> "FAPI 2.0 Security Profile, 5.3.3. Requirements for clients, 5.3.3.2. Authorization code flow"

1. shall use the authorization code grant described in \[RFC6749];

### ☑️ PKCE

The `code_challenge` request parameter must be set to an appropriate value and the `code_challenge_method` request parameter must be set to `S256`.

> "FAPI 2.0 Security Profile, 5.3.3. Requirements for clients, 5.3.3.2. Authorization code flow"

3. shall use PKCE \[RFC7636] with `S256` as the code challenge method

### ☑️ Redirect URI

The `redirect_uri` request parameter must be set and it must be a URI starting with `https`. In this demonstration, we use the redirect URI registered in the client settings.

> "FAPI2 Security Profile, 5.3.2. Requirements for authorization servers, 5.3.2.2. Authorization endpoint flows"

6. shall require the `redirect_uri` parameter in pushed authorization requests

>

8. shall not transmit authorization responses over unencrypted network connections, and, to this end, shall not allow redirect URIs that use the "http" scheme except for native clients that use loopback interface Redirection as described in Section 7.3 of \[RFC8252];

### ☑️ Response Mode

The `response_mode` parameter must be set to `jwt`.

> "FAPI 2.0 Message Signing Profile, 5.4. Signing authorization responses, 5.4.1. Requirements for Authorization Servers"
>
> Authorization servers implementing FAPI2 authorization response signing

1. shall support, require use of, and issue signed authorization responses via JWT Secured Authorization Response Mode for OAuth 2.0 \[JARM].

> "FAPI 2.0 Message Signing Profile, 5.4. Signing authorization responses, 5.4.2. Requirements for Clients"
>
> Clients implementing FAPI2 authorization response signing

1. shall set the response\_mode to jwt in the authorization request as defined in \[JARM];

Taking all of the requirements above into account, the request that the client send to the pushed authorization endpoint would be like below.

```
POST /par HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded

client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer
&client_assertion=eyJraWQi...
&client_id={Client ID}
&response_type=code
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
&scope=myscope
&code_challenge=E9Melhoa...
&code_challenge_method=S256
&response_mode=jwt
```

After the authorization server receives the request from the client, the authorization server calls Authlete `/pushed_auth_req` API including the received parameters.

Below is a curl command that simulates a request from the authorization server to Authlete `/pushed_auth_req` API.

```shell theme={null}
curl -s -X POST https://us.authlete.com/api/{Service ID}/pushed_auth_req \
-H 'Authorization: Bearer {Authlete API Access Token}' \
-H 'Content-type: application/json' \
-d '{"parameters":"client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&client_assertion=eyJraWQi...&client_id={Client ID}&response_type=code&redirect_uri=https%3A%2F%2Fclient.example.com%2Fcb&scope=myscope&code_challenge=E9Melhoa...&code_challenge_method=S256&response_mode=jwt"}'
```

A successful response from the API contains a request URI. The response would look like below.

```json theme={null}
{
  "resultCode": "A245001",
  "resultMessage": "[A245001] Successfully registered a request object for client ({Client ID}), URI is urn:ietf:params:oauth:request_uri:6uOtgZjBYPPspJLf630c8iJfi4xql_G3R7MKMjgTxRk.",
  "action": "CREATED",
  "requestUri": "urn:ietf:params:oauth:request_uri:6uO...",
  "responseContent": "{\"expires_in\":300,\"request_uri\":\"urn:ietf:params:oauth:request_uri:6uO...\"}"
}
```

### 2. Authorization Request & Response

<img src="https://mintcdn.com/authlete/oZd1VUaYFwHO2MBx/protocols-and-flows/compliance-profiles/auth-req-and-res-cropped.png?fit=max&auto=format&n=oZd1VUaYFwHO2MBx&q=85&s=0b466ef0b8ed17de0e885067db23f9cf" width="2880" height="1185" data-path="protocols-and-flows/compliance-profiles/auth-req-and-res-cropped.png" />

After obtaining a request URI in step 1, the client sends an authorization request, including the request URI, to the authorization endpoint of the authorization server. The request appears as below.

```bash theme={null}
GET /oauth/authorize?client_id={Client ID}&request_uri=urn:ietf:params:oauth:request_uri:6uO... HTTP/1.1
Host: server.example.com
```

When the authorization server receives the request from the client, the authorization sever calls Authlete `/auth/authorization` API.

Below is a curl command that simulates a request from the authorization server to Authlete `/auth/authorization` API.

```shell theme={null}
curl -s -X POST https://us.authlete.com/api/{Service ID}/auth/authorization \
-H 'Authorization: Bearer {Authlete API Access Token}' \
-H 'Content-type: application/json' \
-d '{"parameters":"client_id={Client ID}&request_uri=urn:ietf:params:oauth:request_uri:6uO..."}'
```

A successful response from the API would be like below.

```json theme={null}
{
  "resultCode": "A004001",
  "resultMessage": "[A004001] Authlete has successfully issued a ticket to the service (API Key = {Service API Key}) for the authorization request from the client (ID = {Client ID}). [response_type=code, openid=false]",
  "ticket": "CBKnPeMO...",
  ...
}
```

After the authorization server receives a successful response from `/auth/authorization` API, the end-user authorizes/denies the client's request in the browser. The authorization result is then conveyed to the authorization server and the authorization server calls Authlete `/auth/authorization/issue` API with the result.

Below is a curl command that simulates a request from the authorization server to Authlete `/auth/authorization/issue` API.

```shell theme={null}
curl -s -X POST https://us.authlete.com/api/{Service ID}/auth/authorization/issue \
-H 'Authorization: Bearer {Authlete API Access Token}' \
-H 'Content-type: application/json' \
-d '{"ticket":"CBKnPeMO...","subject":"john","result":"AUTHORIZED"}'
```

A successful response from the API will include an authorization code, as shown below.

```json theme={null}
{
  "resultCode": "A040001",
  "resultMessage": "[A040001] The authorization request was processed successfully.",
  "authorizationCode": "smseP17u...",
  "responseContent": "https://client.example.org/cb?response=eyJraWQi...",
  ...
}
```

You can find the `response` parameter in `responseContent`, and it contains a JWT (`eyJraWQi...`).
The payload of the JWT contains an authorization code as follows.

```json theme={null}
{
  "aud": "{Client ID}",
  "code": "smseP17u...",
  "iss": "https://server.example.com",
  "exp": 1702725889
}
```

### 3. Token Request & Response

<img src="https://mintcdn.com/authlete/pc0lPZhy9Zo_eIBR/protocols-and-flows/compliance-profiles/token-req-and-res-cropped.png?fit=max&auto=format&n=pc0lPZhy9Zo_eIBR&q=85&s=999f1bef1e4d482269f1658c73783c8f" width="2860" height="846" data-path="protocols-and-flows/compliance-profiles/token-req-and-res-cropped.png" />

After obtaining an authorization code in step 3, the client sends a request, including the authorization code, to the token endpoint. Similar to the requirement at the pushed authorization request endpoint, the token endpoint authenticates the client using `private_key_jwt`.

Also, we assume that the authorization server issues access tokens that are sender-constrained with DPoP based on the following requirements:

> "FAPI 2.0 Security Profile, 5.3.2. Requirements for authorization servers, 5.3.2.1. General requirements"

4. shall only issue sender-constrained access tokens,

>

5. shall use one of the following methods for sender-constrained access tokens:

>

* MTLS as described in \[RFC8705],

>

* DPoP as described in \[RFC9449];

> "FAPI 2.0 Security Profile, 5.3.3. Requirements for clients, 5.3.3.1. General requirements"

1. shall support sender-constrained access tokens using one or both of the following methods:

>

* MTLS as described in \[RFC8705],

>

* DPoP as described in \[RFC9449];

Therefore, the client must present a DPoP proof JWT for the authorization server to obtain a sender-constrained access token.

Note that DPoP proof JWTs must be signed with `PS256`, `ES256` or `EdDSA`.

> "FAPI 2.0 Security Profile, 5.4. Cryptography and secrets, 5.4.1. General requirements"

1. Authorization servers, clients, and resource servers when creating or processing JWTs shall

> * adhere to \[RFC8725];
> * use `PS256`, `ES256`, or `EdDSA` (using the `Ed25519` variant) algorithms; and
> * not use or accept the none algorithm.

Taking the requirements above into account, a request to the token endpoint would look like as below.

```
POST /oauth/token HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
DPoP: eyJ0eXAi...

client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer
&client_assertion=eyJhbGci...
&client_id={Client ID}
&code=smseP17u...
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
&grant_type=authorization_code
&code_verifier=ErRt0wrt...
```

After the token endpoint receives a request from the client, the authorization server calls Authlete `/auth/token` API.

Below is a curl command that simulates a request from the authorization server to Authlete `/auth/token` API.

```shell theme={null}
curl -s -X POST https://us.authlete.com/api/{Service ID}/auth/token \
-H 'Authorization: Bearer {Authlete API Access Token}' \
-H 'Content-type: application/json' \
-d '{"parameters":"client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&client_assertion=eyJraWQi...&client_id={Client ID}&code=smseP17u...&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb&grant_type=authorization_code&code_verifier=ErRt0wrt...","dpop":"eyJ0eXAi..."}'
```

A successful response from the API will include an access token, as shown below.

```json theme={null}
{
  "resultCode": "A050001",
  "resultMessage": "[A050001] The token request (grant_type=authorization_code) was processed successfully.",
  "accessToken": "7i9xPkbk...",
  ...
}
```

### 4. Protected Resource

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/introspection-req-and-res-cropped.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=ae64c117a52e371781b915093ada1985" width="2880" height="843" data-path="protocols-and-flows/compliance-profiles/introspection-req-and-res-cropped.png" />

After completing all the steps above, the client gets an access token and can access a protected resource endpoint of the resource server with the obtained access token as follows.

```
GET /api/sample HTTP/1.1
Authorization: DPoP 7i9xPkbk...
DPoP: eyJ0eXAi...
Host: resource.example.com
```

Note that the client needs to present a DPoP proof JWT to the resource server's endpoint along with the access token.

When the resource server receives the request from the client, the resource server calls Authlete `/auth/introspection` API to verify the access token.

Below is a curl command that simulates a request from the resource server to Authlete `/auth/introspection` API.

```shell theme={null}
curl -s -X POST https://us.authlete.com/api/{Service ID}/auth/introspection \
-H 'Authorization: Bearer {Authlete API Access Token}' \
-H 'Content-type: application/json' \
-d '{"token":"7i9xPkbk...","dpop":"eyJ0eXAi...","htm":"GET","htu":"https://resource.example.com/api/sample"}'
```

A successful response from the API would be like below.

```json theme={null}
{
  "resultCode": "A056001",
  "resultMessage": "[A056001] The access token is valid.",
  "action": "OK",
  ...
}
```
