---
title: Authorization code grant with PAR
description: /oauth2/par
component: pingam
version: 8.1
page_id: pingam:am-oauth2:oauth2-authz-grant-par
canonical_url: https://docs.pingidentity.com/pingam/8.1/am-oauth2/oauth2-authz-grant-par.html
keywords: ["OAuth 2.0", "Endpoints", "Authorization", "JWT", "Grant Flow", "PAR", "REST API"]
page_aliases: ["oauth2-guide:oauth2-authz-grant-par.adoc"]
section_ids:
  oauth2-authz-par-flow: The authorization code grant with PAR flow
  oauth2-authz-par-demo: Demonstrate the authorization code grant with PAR flow
  prepare-par-demo: Prepare the demonstration
  proc-par-requesturi: Get a PAR request URI
  proc-par-browser: Get an authorization code using a browser
  proc-par-no-browser: Get an authorization code using REST
  proc-par-token: Exchange an authorization code for an access token
---

# Authorization code grant with PAR

* Endpoints

  * [/oauth2/par](oauth2-par-endpoint.html)

  * [/oauth2/authorize](oauth2-authorize-endpoint.html)

  * [/oauth2/access\_token](oauth2-access_token-endpoint.html)

The pushed authorization request (PAR) endpoint provides enhanced security and cryptographic integrity when used with the authorization code grant flow, and optionally, in conjunction with PKCE.

PAR lets the authorization server authenticate the client before making an authorization request to enable early detection of invalid or illegal requests.

To further protect authorization details when passing through third-party applications, clients can use JWT-based request objects (as defined in [RFC9101](https://www.rfc-editor.org/info/rfc9101)) to wrap confidential and potentially complex request parameters.

In response to this pre-authorization backchannel request, the client receives a request URI that's used to reference the payload data in subsequent interactions with the server.

|   |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | * PAR is optional by default. To *enforce* the use of the PAR endpoint to initiate authorization requests, enable Require Pushed Authorization Requests in the AM admin UI:

  * To force all clients to use PAR, configure the OAuth 2.0 provider [advanced settings](../setup/services-configuration.html#global-oauth-oidc-advanced).

  * To force an individual client to use PAR, configure the [client settings](oauth2-register-client.html#configure-oauth2-oidc-client-advanced).

* The [PAR](https://www.rfc-editor.org/rfc/rfc9126.html) and [JAR](https://www.rfc-editor.org/rfc/rfc9101.html#section-5.2) specifications indicate the following:

  * The authorization server should ignore authorize parameters outside the `request_uri`.

  * When sending a JWT-Secured Authorization Request (JAR), the `request_uri` *must* be an `https` URI.

  To enforce this behavior in AM, set the [am.oauth2.request.object.restrictions.enforced](../setup/server-advanced.html#am.oauth2.request.object.restrictions.enforced) advanced server property to `true`. |

## The authorization code grant with PAR flow

![AM supports the authorization code grant flow with PAR.](_images/oauth2-authz-par.svg)Figure 1. OAuth 2.0 authorization code grant with PAR flow

1. The client pushes a request to the PAR endpoint, providing both client and request details.

2. AM validates both client and request and, if successful, returns a request URI as a reference to the request payload and an expiry period for the request URI.

3. The client receives a request to access a protected resource. To access the resources, the client requires authorization from the resource owner.

4. The client redirects the resource owner's user-agent to AM.

5. AM authenticates the resource owner, confirms resource access, and gathers consent if not previously saved.

6. The client requests an authorization code, typically through a web browser, by passing in the `request_uri` and `client_id`.

7. AM validates the `client_id` against the request and, if successful, returns the authorization code to the client.

8. The client authenticates to AM using the received code in exchange for an access token.

   |   |                                                                                             |
   | - | ------------------------------------------------------------------------------------------- |
   |   | This example assumes a confidential client. Public clients aren't required to authenticate. |

9. If the authorization code is valid, AM returns an access token (and a refresh token, if configured) to the client.

10. The client requests access to the protected resources from the resource server.

11. The resource server contacts AM to validate the access token.

12. AM validates the token and responds to the resource server.

13. If the token is valid, the resource server lets the client access the protected resource.

## Demonstrate the authorization code grant with PAR flow

Follow these steps to get a PAR request URI and an authorization code to exchange for an access token:

1. [Prepare the demonstration](#prepare-par-demo)

2. [Get a PAR request URI](#proc-par-requesturi)

3. [Get an authorization code using REST](#proc-par-no-browser) or [Get an authorization code using a browser](#proc-par-browser)

4. [Exchange an authorization code for an access token](#proc-par-token)

### Prepare the demonstration

This demonstration assumes the following configuration:

* AM is configured as an OAuth 2.0 authorization server. Ensure that:

  * The `code` plugin is configured in the Response Type Plugins field.

  * The `Authorization Code` grant type is configured in the Grant Types field.

  * The `PAR Request URI Lifetime` attribute is set to a value sufficient to cover the duration of the PAR request.

  Find more information in [Authorization server configuration](oauth2-configure-authz.html).

* A confidential client called `myClient` is registered in AM with the following configuration:

  * **Client secret**: `mySecret`

  * **Scopes**: `write`

  * **Response Types**: `code`

  * **Grant Types**: `Authorization Code`

  Find more information in [Client application registration](oauth2-register-client.html). Complete these steps to prepare the authorization code grant with PAR flow demonstration:

### Get a PAR request URI

As the client, call AM's [/oauth2/par](oauth2-par-endpoint.html) endpoint. Specify parameters directly in the request body. Alternatively, for large or sensitive data, AM supports the [JWT-Secured Authorization Request (JAR)](https://www.rfc-editor.org/info/rfc9101) standard for PAR, which lets you wrap parameters in a signed and encrypted JWT. When using JAR, sign the request JWT with the client's private key and encrypt it with the authorization server's public key. You can obtain the authorization server's public key from its JWKS URI.

Example parameters with a JWT:

* **client\_id**=*your-client-id*

* **client\_secret**=*your-client-secret*

* **`request`**: `signed-encrypted-jwt-value`

Example parameters without a JWT:

* **client\_id**=*your-client-id*

* **client\_secret**=*your-client-secret*

* **redirect\_uri**=*your-redirect-uri*

* **scope**=write

* **response\_type**=code,

* **code\_challenge**=QR1D-7w1-rOQvlFe1CeqZigqaIpmZXatDMVvZ50o

* **code\_challenge\_method**=S256

Example PAR request with a JWT:

```bash
$ curl \
--request POST \
--data "client_id=myClient" \
--data "client_secret=mySecret" \
--data "request=eyJhbGciOiJIUzI1NiJ…​mnRTwgPGTqkp5UBTVWaA_CifxWx1ikcZofOas" \
"https://am.example.com:8443/am/oauth2/realms/root/realms/alpha/par"
```

Example PAR request without a JWT:

```bash
$ curl \
--request POST \
--data "client_id=myClient" \
--data "client_secret=mySecret" \
--data "response_type=code" \
--data "scope=write" \
--data "code_challenge=QR1D-7w1-rOQvlFe1CeqZigqaIpmZXatDMVvZ50o" \
--data "code_challenge_method=S256" \
--data "redirect_uri=https://www.example.com:443" \
"https://am.example.com:8443/am/oauth2/realms/root/realms/alpha/par"
```

On success, AM returns the following:

```bash
{
  "request_uri": "C2c3yhu2IApAELttmZtfPNPQaIJxvTCHk", (1)
  "expires_in": 90 (2)
}
```

|       |                                                                  |
| ----- | ---------------------------------------------------------------- |
| **1** | `request_uri`: A reference to the PAR request payload.           |
| **2** | `expires_in`: The validity period of the request URI in seconds. |

### Get an authorization code using a browser

1. Ensure the client has retrieved a request URI by following the steps described in [Get a PAR request URI](#proc-par-requesturi).

2. The client redirects the resource owner's user-agent to AM's [/oauth2/authorize](oauth2-authorize-endpoint.html) endpoint, including the following parameters:

   * **client\_id**=*your-client-id*

   * **response\_type**=code

   * **redirect\_uri**=*your-redirect-uri*

   * **request\_uri**=*the-PAR-request-uri*

   For example:

   ```none
   https://am.example.com:8443/am/oauth2/realms/root/realms/alpha/authorize \
   ?client_id=myClient \
   &response_type=code \
   &request_uri=C2c3yhu2IApAELttmZtfPNPQaIJxvTCHk
   &scope=write \
   &redirect_uri=https://www.example.com:443/callback
   ```

   |   |                                                                                                                                                                          |
   | - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
   |   | The URL is split and spaces added for readability purposes.The `scope` parameter is optional if default values are configured in the authorization server or the client. |

3. The resource owner authenticates to AM. In this demonstration, they log in using the default tree configured for the realm.

4. On a successful login, AM presents the AM consent screen unless AM is configured to use [implied consent](oauth2-manage-consent.html#skip-consent).

   ![The OAuth 2.0 AM user interface consent screen requesting access to the write scope.](_images/oauth2-authz-page-xui.png)Figure 2. OAuth 2.0 consent screen

5. Click Allow to consent.

   AM redirects the resource owner to the URL specified in the `redirect_uri` parameter.

6. Inspect the URL in the browser.

   It contains a `code` parameter with the authorization code AM issued.

   For example:

   `http://www.example.com/callback?code=g5B3qZ8rWzKIU2xodV_kkSIk0F4&scope=write&iss…​`

7. The client performs the steps in [Exchange an authorization code for an access token](#proc-par-token) to exchange the authorization code for an access token.

### Get an authorization code using REST

1. Ensure the client has retrieved a request URI by following the steps in [Get a PAR request URI](#proc-par-requesturi).

2. [Authenticate](../am-authentication/authn-rest.html) as the resource owner (`bjensen` in our example):

   ```bash
   $ curl \
   --request POST \
   --header "Content-Type: application/json" \
   --header "X-OpenAM-Username: bjensen" \
   --header "X-OpenAM-Password: Ch4ng31t" \
   --header "Accept-API-Version: resource=2.0, protocol=1.0" \
   'https://am.example.com:8443/am/json/realms/root/realms/alpha/authenticate'
   {
       "tokenId":"AQIC5wM…​TU3OQ*",
       "successUrl":"/am/console",
       "realm":"/alpha"
   }
   ```

3. As the client, call the [/oauth2/authorize](oauth2-authorize-endpoint.html) endpoint to request the authorization code. Provide bjensen's SSO token in a cookie and the following parameters:

   * **`client_id`**: `myClient`

   * **`request_uri`**: `par_request_uri`

   * **`csrf`**: `bjensens-tokenId`

   * **`decision`**: `allow`

   Find more information on the parameters supported by this endpoint in [/oauth2/authorize](oauth2-authorize-endpoint.html).

   For example:

   ```bash
   $ curl --dump-header - \
   --request POST \
   --cookie "iPlanetDirectoryPro=AQIC5wM…​TU3OQ*" \
   --data "client_id=myClient" \
   --data "request_uri=C2c3yhu2IApAELttmZtfPNPQaIJxvTCHk" \
   --data "csrf=AQIC5wM…​TU3OQ*" \
   --data "decision=allow" \
   "https://am.example.com:8443/am/oauth2/realms/root/realms/alpha/authorize"
   ```

   If AM can authenticate the user and the client, it returns an HTTP 302 response with the authorization code appended to the redirection URL:

   ```bash
   HTTP/2 302
   …​
   location: https://www.example.com:443/callback?code=authorization-code&iss…​
   …​
   ```

4. Perform the steps in [Exchange an authorization code for an access token](#proc-par-token) to exchange the authorization code for an access token.

### Exchange an authorization code for an access token

As the client, call the [/oauth2/access\_token](oauth2-access_token-endpoint.html) endpoint to exchange the authorization code for an access token. Provide the following parameters:

* **grant\_type**=authorization\_code

* **code**=*your-authorization-code*

* **redirect\_uri**=*your-redirect-uri*

* **code\_verifier**=*your-code-verifier*

Confidential clients can authenticate to the OAuth 2.0 endpoints in several ways. This example uses the following form parameters:

* **client\_id**=*your-client-id*

* **client\_secret**=*your-client-secret*

Find more information in [OAuth 2.0 client authentication](oauth2-client-auth.html).

For example:

```bash
$ curl \
--request POST \
--data "grant_type=authorization_code" \
--data "code=g5B3qZ8rWzKIU2xodV_kkSIk0F4" \
--data "client_id=myClient" \
--data "client_secret=mySecret" \
--data "redirect_uri=https://www.example.com:443/callback" \
--data "code_verifier=082b7ab3042995bcb3163ec8…​" \
"https://am.example.com:8443/am/oauth2/realms/root/realms/alpha/access_token"
```

The `client_id` and `redirect_uri` parameters specified in this call must match those used as part of the authorization code request, or the authorization server will not validate the code.

The authorization server returns an access token in the `access_token` property. For example:

```bash
{
  "access_token": "sbQZuveFumUDV5R1vVBl6QAGNB8",
  "scope": "write",
  "token_type": "Bearer",
  "expires_in": 3599
}
```

|   |                                                                                                                                                                              |
| - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | The authorization server can also issue refresh tokens at the same time the access tokens are issued. Find more information in [Refresh tokens](oauth2-refresh-tokens.html). |
