# 1. Pushed Authorization Request (PAR) Endpoint

The **Pushed Authorization Request (PAR)** flow is a **mandatory** extension of the OIDC authorization code flow for FAPI 2.0, as defined in [RFC 9126](https://datatracker.ietf.org/doc/html/rfc9126).

It allows the Relying Party (RP) to register sensitive authorization request parameters directly with Corppass via a *secure back-channel `POST` request*. By "pushing" these parameters directly to the server instead of encoding them in the browser URL, this significantly reduces the risk of leaking sensitive data (e.g., `scope`, `redirect_uri`) and ensures integrity by authenticating the request before the user interaction begins.

## Request

To initiate the flow, send a `POST` request to the PAR Endpoint URL obtained from the [OpenID Discovery Endpoint](https://docs.corppass.gov.sg/technical-specifications/corppass-authorization-api-fapi-2.0/endpoints/0.-well-known-endpoints/openid-discovery-endpoint) (`pushed_authorization_request_endpoint`).

```http
POST /request
```

### Request Headers

<table><thead><tr><th width="190.41796875">Header</th><th width="114.15625">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>Content-Type</code></td><td>Yes</td><td><p>Indicates the encoding format of the request body.</p><p></p><p>Must be set to <code>application/x-www-form-urlencoded</code>. </p></td></tr><tr><td><code>DPoP</code></td><td>Yes</td><td><p>The JWK Thumbprint of your proof-of-possession public key. The JWK thumbprint should be computed using the SHA256 hash algorithm, and encoded using base64url.<br></p><p>Optional if you provide the DPoP Proof JWK in the <code>dpop_jkt</code> request parameter (see Request Body section below). If both are provided, they <strong>must</strong> match.<br><br>For simplicity, we <strong>recommend sending the <code>DPoP</code> header</strong> over the use of <code>dpop_jkt</code> request parameter, as the <code>DPoP</code> header is mandatory for later steps.<br><br>Refer to the <a href="../key-concepts/demonstrating-proof-of-possession-dpop">Demonstrating Proof of Possession</a> section for more details.</p></td></tr></tbody></table>

### Request Body

<table><thead><tr><th width="193.078125">Field</th><th width="114.41796875">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>client_id</code></td><td>Yes</td><td>The client identifier assigned to the RP during onboarding.</td></tr><tr><td><code>client_assertion</code></td><td>Yes</td><td><p>A JWT identifying the client.</p><p></p><p>Refer to <a href="../key-concepts/client-assertion-jwt">Client Assertion JWT</a> section for more details.</p></td></tr><tr><td><code>client_assertion_type</code></td><td>Yes</td><td><p>The type of client assertion.</p><p></p><p>Must be set to <code>urn:ietf:params:oauth:client-assertion-type:jwt-bearer</code>, as mandated by OIDC specifications.</p></td></tr><tr><td><code>code_challenge</code></td><td>Yes</td><td><p>The encoded, hashed value of the client-generated <code>code_verifier</code>.</p><p></p><p>Refer to <a href="../key-concepts/proof-key-of-code-exchange-pkce">Proof Key of Code Exchange</a> for more details.</p></td></tr><tr><td><code>code_challenge_method</code></td><td>Yes</td><td><p>The method used to generate the <code>code_challenge</code> from the <code>code_verifier</code>.</p><p></p><p>Must be set to <code>S256</code>, as mandated by FAPI 2.0 specifications.</p></td></tr><tr><td><code>response_type</code></td><td>Yes</td><td><p>The authorization processing flow to use.</p><p></p><p>Must be set to <code>code</code>, as mandated by FAPI 2.0 specifications.</p></td></tr><tr><td><code>redirect_uri</code></td><td>Yes</td><td>The callback URL where Corppass will redirect the user upon authorisation.<br><br>The value must match one of the redirect URLs that were pre-registered during onboarding.</td></tr><tr><td><code>scope</code></td><td>Yes</td><td><p>Space-delimited list of requested scopes.</p><p></p><p>Each scope grants access to a set of <em>entity</em> or <em>acting user</em>'s attributes called claims. Once authorised, these claims are returned in an <em>ID Token</em> (via the <a href="3.-token-endpoint">Token Endpoint</a>) and/or made available via the <a href="4.-userinfo-endpoint"><em>Userinfo Endpoint</em></a>.</p><p><br>Must include <code>openid</code> scope. Unrecognised or unauthorised scopes will result in an error.</p><p></p><p>Refer to the <a href="../scopes">Scopes</a> section for more details.</p></td></tr><tr><td><code>state</code></td><td>Yes</td><td><p>A client-provided value used to maintain state between the request and the callback. It helps mitigate Cross-Site Request Forgery (CSRF, XSRF) attacks.</p><p></p><p>This value should be unique, non-guessable, and generated for each authorization session.</p><p></p><p>The value is returned in the authorization response. The RP must validate that the returned <code>state</code> matches the value originally provided.</p></td></tr><tr><td><code>nonce</code></td><td>Yes</td><td><p>A client-provided value used to mitigate replay attacks.</p><p></p><p>This value should be unique, non-guessable, and generated for each authorization session.</p><p></p><p>The value is returned in the ID Token. The RP must validate that the returned <code>nonce</code> matches the value originally provided.</p></td></tr><tr><td><code>acr_values</code></td><td>No</td><td><p>Optional. A space-delimited string indicating desired level of assurance (LoA) for the authentication.</p><p><br>If multiple values are provided, they should be listed in descending order of preference. The authorization server will use the first supported / available value.</p><p></p><p>If not provided, Corppass defaults to the client's configured level.</p><p></p><p>Supported values:</p><ul><li><p><code>urn:singpass:authentication:loa:2</code></p><ul><li>This refers to an assurance level of 2, meaning that only 2FA is required.</li></ul></li></ul><p><br>More value types may be introduced in the future.</p></td></tr><tr><td><code>authentication_context_type</code></td><td>Yes</td><td>A value from a predefined list describing the type of transaction for which your user is performing the authentication. This is used for anti-fraud purposes.<br><br>Refer to the <a href="1.-pushed-authorization-request-par-endpoint/authentication-context-parameters">Authentication Context Parameters</a> section for more details.</td></tr><tr><td><code>authentication_context_message</code></td><td>No</td><td>Optional. A string value providing context on what users are performing authentication for. This will be displayed to users during authentication.</td></tr><tr><td><code>dpop_jkt</code></td><td>No</td><td>The JWK Thumbprint of your proof-of-possession public key. The JWK thumbprint should be computed using the SHA256 hash algorithm, and encoded using base64url.<br><br>Optional if <code>DPoP</code> header is provided. If both are provided, they <strong>must</strong> match.<br><br>For simplicity, we <strong>recommend sending the <code>DPoP</code> header</strong> over the use of <code>dpop_jkt</code> request parameter, as the <code>DPoP</code> header is mandatory for later steps.<br><br>Refer to the <a href="../key-concepts/demonstrating-proof-of-possession-dpop">Demonstrating Proof of Possession</a> section for more details.</td></tr></tbody></table>

### Sample Request

```http
POST /request
Content-Type: application/x-www-form-urlencoded
DPoP: <signed-DPoP-JWT>

client_id=51YUlwazLASM7aqMiBNW
&client_assertion=eyJ...
&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
&code_challenge=VQbq2FQzvY12kTkE-FoLmGHim5W7LRknTNYTUKuCKcE
&code_challenge_method=S256
&response_type=code
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcallback
&scope=openid%20authinfo
&state=5de6a954-a762-4975-a8f4-b692cc35b964
&nonce=4a0bb161-e3bb-4a56-9d75-ebea5de7a32c
&acr_values=urn:singpass:authentication:loa:2
&authentication_context_type=APP_AUTHENTICATION_DEFAULT
&authentication_context_message=login%20as%20corporate%20user
&dpop_jkt=boPCS...
```

## Success Response

If the request is valid, Corppass registers the provided parameters and returns a JSON response containing a `request_uri`.

### Response Body

<table><thead><tr><th width="214.66796875">Field</th><th width="136.328125">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>request_uri</code></td><td>String</td><td><p>A reference to the authorization payload.</p><p></p><p>Use this in the subsequent redirect to the <a href="2.-authorization-endpoint">Authorization Endpoint</a>.</p></td></tr><tr><td><code>expires_in</code></td><td>Number</td><td><p>The lifetime of the <code>request_uri</code> in seconds.</p><p>This is set to 60 seconds.</p></td></tr></tbody></table>

### Sample Response

```json
{
  "request_uri": "urn:ietf:params:oauth:request_uri:h8YQPVV0Dgm5MGaD_koAm",
  "expires_in": 60
}
```

## Error Response

If the request is malformed, unauthorised, or contains invalid parameters, Corppass returns a JSON response containing an error code and description.

### Response Body

<table><thead><tr><th width="214.66796875">Field</th><th width="136.328125">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>error</code></td><td>String</td><td><p>The error code identifying the type of error.</p><p><br>See <a href="#error-codes">Error Codes</a> below.</p></td></tr><tr><td><code>error_description</code></td><td>String</td><td>A human-readable description of the error.</td></tr><tr><td><code>state</code></td><td>String</td><td>The same <code>state</code> parameter value provided by the client in the pushed authorization request, returned as-is.</td></tr></tbody></table>

#### Error Codes

<table><thead><tr><th width="204.31640625">Error Code</th><th width="166.359375">HTTP Status</th><th>Error Description</th></tr></thead><tbody><tr><td>invalid_request</td><td>400</td><td>The request is missing a required parameter, includes an unsupported value, or is malformed. </td></tr><tr><td>invalid_client</td><td>400 / 401</td><td>Client authentication failed due to a missing, invalid, expired, or improperly formatted client credential or assertion.</td></tr><tr><td>invalid_scope</td><td>400</td><td>The requested scope is invalid, unknown, malformed, or exceeds the scope granted to the client.</td></tr><tr><td>invalid_dpop_proof</td><td>401</td><td>The DPoP proof is invalid, expired, malformed, or failed verification.</td></tr><tr><td>server_error</td><td>500</td><td>The authorization server encountered an unexpected internal error while processing the request.</td></tr><tr><td>temporarily_unavailable</td><td>503</td><td>The server is temporarily unable to handle the request due to maintenance or high load.</td></tr></tbody></table>

### Sample Response

```json
{
  "error": "invalid_request",
  "error_description": "The redirect_uri is not valid for the given client",
  "state": "5de6a954-a762-4975-a8f4-b692cc35b964"
 }
```

## Next Steps

**Redirect the User:** Upon successful retrieval of the `request_uri` from the PAR response, the next step is to redirect the user's browser to the *Authorization Endpoint*.

The `request_uri` serves as a secure reference to the parameters registered in this step and is used to construct the redirect URL, replacing the full list of query parameters typically used in legacy flows.

**Proceed to** [**2. Authorization Endpoint**](https://docs.corppass.gov.sg/technical-specifications/corppass-authorization-api-fapi-2.0/endpoints/2.-authorization-endpoint) **to redirect the user and obtain the Authorization Code.**
