# 1. The Authorization Request

The first step in the Singpass authentication flow is the authorization request. This involves kicking off a Login or Myinfo (v5) transaction by redirecting users to Singpass' login page, while also providing some information about what this transaction is for (e.g. the data you wish to retrieve).

Singpass requires the use of Pushed Authorization Requests (PAR) ([RFC 9126](https://datatracker.ietf.org/doc/html/rfc9126)), so this step actually consists of the following sub-steps:

1. First, send a POST request to our **`pushed_authorization_request_endpoint`** (as defined in our [OpenID configuration](https://docs.developer.singpass.gov.sg/docs/technical-specifications/technical-concepts/openid-connect-discovery)). If successful, you will receive a response containing a `request_uri`.
2. Next, using that `request_uri` and our **`authorization_endpoint`** (also defined in our [OpenID configuration](https://docs.developer.singpass.gov.sg/docs/technical-specifications/technical-concepts/openid-connect-discovery)), construct an authorization URL.
3. Finally, redirect the user to that authorization URL.

More details about these sub-steps are provided below.

## 1. Sending the pushed authorization request

The pushed authorization request is a HTTP POST request that is sent to the pushed authorization request endpoint.

Your request should contain a request body in the `application/x-www-form-urlencoded` format. The request body supports a lot of parameters, which can be divided into several groups: parameters specified by basic OIDC, parameters for PKCE, parameters for DPoP, and Singpass-specific parameters.

### Basic OIDC Parameters

These are parameters that are specified as part of the original OIDC specifications. More information about them can be viewed in the [official specifications](https://openid.net/specs/openid-connect-core-1_0.html).

<table><thead><tr><th width="200.8359375">Parameter</th><th width="327.26953125">Description</th><th>Data type</th></tr></thead><tbody><tr><td><code>response_type</code></td><td>The authorization processing flow to be used.</td><td>Only the value <code>code</code> is supported, as mandated by FAPI2.0 specifications.</td></tr><tr><td><code>scope</code></td><td><p>A space-delimited string, representing a list of scopes that you are requesting.</p><p><br>The scopes that you request will determine the data that is returned in the ID token and in the userinfo endpoint.</p></td><td><p>A space-delimited string representing a list of scopes. For Myinfo apps, See our <a href="https://docs.developer.singpass.gov.sg/docs/data-catalog-myinfo/catalog">Data Catalog</a> for the allowed values.</p><p>For Login apps, there are some basic scopes that are allowed. The scopes are <code>user.identity</code> , <code>name</code>, <code>email</code>, and <code>mobileno</code> . See <a href="4.-parsing-the-id-token">Parsing the ID token</a> for more details.</p><p>The <code>openid</code> scope <strong>must</strong> be specified, as per the OIDC specifications.<br><br>In addition to the scopes listed in the Data Catalog, the <code>sub_account</code> scope is also supported. See <a href="4.-parsing-the-id-token">Parsing the ID token</a> for more details.</p></td></tr><tr><td><code>state</code></td><td><p>A session-based, unique, and non-guessable value that you should generate per auth session. This is used to mitigate Cross-Site Request Forgery (CSRF) attacks.</p><p>This parameter should be uniquely generated for each request and set by your backend. The generated value should be persisted in the backend and associated with your user's session, as it will be needed later.<br><br>This string must be generated in a cryptographically secure way, and should ideally be at least 30 characters long. We recommend using a version 4 UUID for this purpose.</p></td><td>A string with a maximum length of 255 characters. It must match the regular expression pattern <code>[A-Za-z0-9/+_-=.]+</code>.</td></tr><tr><td><code>nonce</code></td><td><p>A session-based, unique, and non-guessable value that you should generate per auth session. This is used to mitigate replay attacks.</p><p>Just like the <code>state</code> parameter, this parameter should be uniquely generated for each request and set by your backend. The generated value should be persisted in the backend and associated with your user's session, as it will be needed later.<br><br>This string must be generated in a cryptographically secure way, and should ideally be at least 30 characters long. We recommend using a version 4 UUID for this purpose.</p></td><td><p>A string with a maximum length of 255 characters.</p><p>We recommend using a randomly-generated version 4 UUID for this purpose.<br></p></td></tr><tr><td><code>client_id</code></td><td>The client ID of your registered client, provided by Singpass during app onboarding. It is the App ID found at the top of your app configuration page</td><td>A 32-character case-sensitive alphanumeric string.</td></tr><tr><td><code>redirect_uri</code></td><td>The URL that Singpass will eventually redirect the user to after the user completes the login process using the Singpass App. The value will be validated against the list of redirect URLs that were pre-registered with Singpass during onboarding.</td><td>URL</td></tr><tr><td><code>acr_values</code></td><td><p>A string indicating your preference on the level of assurance required for this authentication. Multiple values, in descending order of preference, may be provided as a space-delimited string.<br><br>Should multiple valid values be provided, we will use the first available level of assurance for the authentication.<br><br>This parameter is applicable only to specific high risk use cases. It should only be used when a higher assurance level is genuinely required, and such use will need to be whitelisted by us.</p><p><br>If you believe your use case may qualify, please submit a request at <a href="https://partnersupport.singpass.gov.sg/">https://partnersupport.singpass.gov.sg</a> for our review.</p></td><td><p>Optional. The possible values are:</p><ul><li><p>urn:singpass:authentication:loa:2</p><ul><li>This refers to an assurance level of 2, meaning that only 2FA is required.</li></ul></li><li><p>urn:singpass:authentication:loa:3</p><ul><li>This refers to an assurance level of 3, meaning that face verification as a third factor is required. Note that you will incur charges starting from 1 Jan 2026 should you opt for an assurance level of 3.</li></ul></li></ul></td></tr><tr><td><code>client_assertion_type</code></td><td>The type of client assertion.</td><td>Must be the string <code>urn:ietf:params:oauth:client-assertion-type:jwt-bearer</code>, as mandated by OIDC specifications.</td></tr><tr><td><code>client_assertion</code></td><td>Your client assertion, which is used for authentication. Refer to <a href="../technical-concepts/generation-of-client-assertion">Generation of Client Assertion for instructions</a> on how this should be generated.</td><td>A string containing the signed JWT.</td></tr></tbody></table>

### PKCE Parameters

These are parameters used for Proof of Key Code Exchange (PKCE), which is an additional security measure put in place to protect the authorization code against misuse by malicious actors.

Read our [guide on PKCE](https://docs.developer.singpass.gov.sg/docs/technical-specifications/technical-concepts/proof-key-for-code-exchange-pkce) to understand what these parameters are for and how to generate the `code_challenge`.

| Parameter               | Description                                                                | Data Type                                                                                |
| ----------------------- | -------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
| `code_challenge`        | The base64url encoded SHA256 hash of a randomly generated `code_verifier`. | A base64url-encoded string.(note: base64url encoding is not the same as base64 encoding) |
| `code_challenge_method` | The method used to generate the `code_challenge` from the `code_verifier`  | Only the value `S256` is supported, as mandated by FAPI 2.0 specifications               |

### DPoP Parameters

These are parameters used to perform authorization code binding to your DPoP key, which is a further security measure to protect the authorization code against misuse by malicious actors.

| Parameter  | Description                                                                                                                                                    | Data Type |
| ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- |
| `dpop_jkt` | 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. | String    |

Note that `dpop_jkt` is only required if your request does not contain the DPoP header (which contains the DPoP Proof JWT).

For simplicity, we recommend sending the [DPoP header](https://docs.developer.singpass.gov.sg/docs/technical-specifications/technical-concepts/demonstrating-proof-of-possession-dpop) in the request rather than using the `dpop_jkt` request parameter, as you will also need to implement DPoP header generation in later steps.

### Singpass-Specific Parameters

These are parameters which are not part of any standard, but are instead specific to Singpass.

<table><thead><tr><th width="279.65234375">Parameter</th><th>Description</th><th>Data Type</th></tr></thead><tbody><tr><td><code>authentication_context_type</code></td><td>A value selected from a predefined list describing the type of transaction that your user is performing the authentication for. This will be used for anti-fraud purposes.</td><td><p><strong>Mandatory and only allowed for Login apps</strong>, </p><p>The list of possible values is provided <a href="#possible-authentication_context_type-values">below</a>.</p></td></tr><tr><td><code>authentication_context_message</code></td><td>A string value providing context on what users are performing authentication for. This will be displayed to users when they are performing authentication. For guidance on writing authentication messages, refer <a href="https://partnersupport.singpass.gov.sg/hc/en-sg/articles/54859616559769-What-is-Authentication-Context-Message">here</a>. All messages are subject to audit and compliance monitoring.</td><td><p>String, with a maximum length of 100 characters.</p><p>The allowable characters are  <code>A-Z</code>, <code>a-z</code>, <code>0-9</code>, <code>&#x3C;space></code>, <code>.</code>, <code>,</code>, <code>-</code>, <code>@</code>,<code>'</code>,<code>!</code>, <code>(</code>, <code>)</code> </p><p>Optional, and <strong>allowed only for Login apps.</strong></p></td></tr><tr><td><code>redirect_uri_https_type</code></td><td>This value describes the type of redirect that you intend to perform. You should specify this as <code>app_claimed_https</code> if you are performing a redirection to a mobile app via an App-claimed https URL.</td><td><p>Either <code>app_claimed_https</code> or <code>standard_https</code>.</p><p>This field is optional; it defaults to <code>standard_https</code> if not provided.</p></td></tr><tr><td><code>app_launch_url</code></td><td>This value is only required if your authentication journey starts and ends for an iOS mobile app. This should be an iOS App Link which will bring the user back to your application after they complete authentication on the Singpass app.</td><td>Optional. <em>only applicable for iOS mobile app integration</em></td></tr></tbody></table>

<details>

<summary>Sample request (Myinfo)</summary>

{% code overflow="wrap" %}

```http
POST /fapi/par HTTP/1.1
Host: stg-id.singpass.gov.sg
Accept-Charset: ISO-8859-1
DPoP: eyJhbGciOiJFUzI1NiIsImp3ayI6eyJhbGciOiJFUzI1NiIsImNydiI6IlAtMjU2Iiwia3R5IjoiRUMiLCJ1c2UiOiJzaWciLCJ4IjoiV2REWGw2SDVjb1g4WjByTDk3UjduMG9KYWpKUXhrRmhXTTVNRzdTZlhnQSIsInkiOiJZeThhcFZRdkVxVDM0ZzhKSDVYUzRIcFBXbTBOMURCaFVMcU5lT3FtTUdJIn0sInR5cCI6ImRwb3Arand0In0.eyJleHAiOjE3NzA3MjE2ODIsImh0bSI6IlBPU1QiLCJodHUiOiJodHRwczovL3N0Zy1pZC5zaW5ncGFzcy5nb3Yuc2cvZmFwaS9wYXIiLCJpYXQiOjE3NzA3MjE1NjIsImp0aSI6ImRjMjYzNDVmLTYzNDEtNGJkYi1hMmVjLTUwZWE4YzRhOGNmMCJ9.QFCtwt8D1VSVEmBuFhHFec7Ii_f981nlIB2s-P-jbHdJR7F22p5r8RC7-lWOExn3vNBmFSP_KGUgo_XIcfhTMw
Content-Type: application/x-www-form-urlencoded
Content-Length: 1037

response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A3001%2Fcallback&client_id=dNGEOSUjyJjTqytbxsspyJAyQIj3tyha&scope=openid%20name%20nationality%20noa&state=5bfda4b1-f67b-4f3c-bbbc-6ca81461fb5a&nonce=5e652418-2373-47f7-8003-43f062244046&code_challenge=52TX5w33iX1u5XEZRmq5IGhZwlajZVVyvdO5ZTqIH6o&code_challenge_method=S256&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&client_assertion=eyJhbGciOiJFUzI1NiIsImtpZCI6InNpZy0yMDI0IiwidHlwIjoiSldUIn0.eyJhdWQiOiJodHRwczovL3NpbmdwYXNzLmdvdi5zZyIsImV4cCI6MTc3MDcyMTY4MiwiaWF0IjoxNzcwNzIxNTYyLCJpc3MiOiJkTkdFT1NVanlKalRxeXRieHNzcHlKQXlRSWozdHloYSIsImp0aSI6IjhiMGJkY2E1LTgxNWEtNDI5OC1hZTJlLThjNGQ3NDU0NjM0ZSIsInN1YiI6ImROR0VPU1VqeUpqVHF5dGJ4c3NweUpBeVFJajN0eWhhIn0.qLAv2f6twnoIRR1VOMs5w3daRStOrznH7guJT-yIfRTtK0RB_iFSpgJAOQ4sSKMl7k5pSyIlNWpqMhZTKSeFIA
```

{% endcode %}

</details>

<details>

<summary>Sample request (Login)</summary>

{% code overflow="wrap" %}

```http
POST /fapi/par HTTP/1.1
Host: stg-id.singpass.gov.sg
Accept-Charset: ISO-8859-1
DPoP: eyJhbGciOiJFUzI1NiIsInR5cCI6ImRwb3Arand0IiwiandrIjp7ImNydiI6IlAtMjU2Iiwia3R5IjoiRUMiLCJ4IjoiRTRhOHp0NTZuMnF3WmE3R1ZPdVV4SHMtUHNQWVIzYnVCNGhtcURyTnV3OCIsInkiOiJWQ3ktckFmN3dMOC1PeWlhdS1kS0dJdmN5THpTMHJULTFlQkxyTGVNM09NIn19.eyJqdGkiOiJmMTM3MzgyYS02MjUwLTQxMjUtYjc5NC0yY2Y2OGRlZTljMzAiLCJodG0iOiJQT1NUIiwiaHR1IjoiaHR0cHM6Ly9zdGctaWQuc2luZ3Bhc3MuZ292LnNnL2ZhcGkvcGFyIiwiaWF0IjoxNzcwODA1ODM5LCJleHAiOjE3NzA4MDU5NTl9.DNeFnNXvmxGr5ZZW9o6mfVoG9uCRbgXxRgyhXWlED0xpkV1uSmNTVSA4QA_VVUNjLEgufNXzRqg7vqeyUyQ6nw
Content-Type: application/x-www-form-urlencoded
Content-Length: 965

response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A3001%2Fcallback&client_id=asC7y1wuFmqwCXys6S5EnaILNcy4yJDx&scope=email%20mobileno%20name%20openid%20user.identity&state=b24a1eae-e01b-4856-affd-3098b9fe0fe8&nonce=e9d4d941-99c4-4db1-90d2-1d77906e3a65&code_challenge=52TX5w33iX1u5XEZRmq5IGhZwlajZVVyvdO5ZTqIH6o&code_challenge_method=S256&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&client_assertion=eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhc0M3eTF3dUZtcXdDWHlzNlM1RW5hSUxOY3k0eUpEeCIsInN1YiI6ImFzQzd5MXd1Rm1xd0NYeXM2UzVFbmFJTE5jeTR5SkR4IiwiYXVkIjoiaHR0cHM6Ly9zdGctaWQuc2luZ3Bhc3MuZ292LnNnL2ZhcGkiLCJpYXQiOjE3NzA4MDU4MzksImV4cCI6MTc3MDgwNTk1OSwianRpIjoiYWZlODg1ZjQtY2FjMC00YmQwLThkMGItMWE3MDkxNzFiMzI1In0.7W_mjPhS6DbvEd32obSany8bqOcrVaS_AvhojjqSHGX6P9OjJUxIdPsjpifO_E8tE3Px-F5egFy2-7nXLLdIFg&authentication_context_type=APP_AUTHENTICATION_DEFAULT&authentication_context_message=Complete%20the%20set%20up%20of%20your%20mobile%20banking%20token
```

{% endcode %}

</details>

#### Possible authentication\_context\_type values

You should select an appropriate `authentication_context_type` value depending on your use case. The possible values for each type of use case are shown below.

<details>

<summary>CPF transactions</summary>

| Event                          | Enum Value                            |
| ------------------------------ | ------------------------------------- |
| Change Payment Mode            | CPF\_CHANGE\_PAYMENT\_MODE            |
| Change daily withdrawal limits | CPF\_CHANGE\_DAILY\_WITHDRAWAL\_LIMIT |
| Profile Update                 | CPF\_PROFILE\_UPDATE                  |
| Link to Bank account           | CPF\_LINK\_BANK\_ACCOUNT              |
| Funds transfer                 | CPF\_FUNDS\_TRANSFER                  |

</details>

<details>

<summary>Banking</summary>

| Event                                          | Enum Value                                      |
| ---------------------------------------------- | ----------------------------------------------- |
| CASA opening                                   | BANK\_CASA\_OPENING                             |
| CASA Initial usage                             | BANK\_CASA\_INITIAL\_USAGE                      |
| Debit/Credit Card application                  | BANK\_CARD\_APPLICATION                         |
| Debit/Credit Card initial usage                | BANK\_CARD\_INITIAL\_USAGE                      |
| Loan Application                               | BANK\_LOAN\_APPLICATION                         |
| Successful addition of local recipient         | BANK\_ADD\_LOCAL\_RECEIPIENT                    |
| Successful addition of overseas recipient      | BANK\_ADD\_OVERSEAS\_RECIPIENT                  |
| Increase transfer limit                        | BANK\_INCREASE\_TRANSFER\_LIMIT                 |
| Report Fraud or suspicious activity            | BANK\_REPORT\_FRAUD\_SUSPICIOUS\_ACTIVITY       |
| Funds transfer                                 | BANK\_FUNDS\_TRANSFER\_LOCAL                    |
| Remit money overseas                           | BANK\_REMIT\_MONEY\_OVERSEAS                    |
| Report lost cards                              | BANK\_REPORT\_LOST\_CARD                        |
| Change of notification method                  | BANK\_CHANGE\_NOTIFICATION\_METHOD              |
| Increase credit card limit                     | BANK\_INCREASE\_CREDIT\_CARD\_LIMIT             |
| Cash advance                                   | BANK\_REQUEST\_CASH\_ADVANCE                    |
| Increased inflow and outflow of funds transfer | BANK\_INCREASE\_INFLOW\_OUTFLOW                 |
| Activation of a dormant account                | BANK\_ACTIVATE\_DORMANT\_ACCOUNT                |
| Login using a new device                       | BANK\_LOGIN\_NEW\_DEVICE                        |
| Login from an unfamiliar IP                    | BANK\_LOGIN\_UNFAMILIAR\_IP                     |
| User Information Update                        | BANK\_UPDATE\_USER\_INFORMATION                 |
| New device registration                        | BANK\_NEW\_DEVICE\_REGISTRATION                 |
| Unlock money lock                              | BANK\_UNLOCK\_MONEY\_LOCK                       |
| Google Pay / Apple Pay card onboarding         | BANK\_GOOGLE\_PAY\_APPLE\_PAY\_CARD\_ONBOARDING |

</details>

<details>

<summary>Other Financial Institutions</summary>

| Event                     | Enum Value                      |
| ------------------------- | ------------------------------- |
| Account Opening           | FI\_ACCOUNT\_OPENING            |
| Link Bank account         | FI\_LINK\_BANK\_ACCOUNT         |
| Increase transfer limit   | FI\_INCREASE\_TRANSFER\_LIMIT   |
| Increase withdrawal limit | FI\_INCREASE\_WITHDRAWAL\_LIMIT |
| Initiate Deposit          | FI\_INITIATE\_DEPOSIT           |

</details>

<details>

<summary>Telcos</summary>

| Event                         | Enum Value                          |
| ----------------------------- | ----------------------------------- |
| SIM card application          | TELCO\_SIM\_CARD\_APPLICATION       |
| Activation of SIM card        | TELCO\_SIM\_CARD\_ACTIVATION        |
| Change of account details     | TELCO\_CHANGE\_ACCOUNT\_DETAILS     |
| Activate Roaming              | TELCO\_ACTIVATE\_ROAMING            |
| Change of notification method | TELCO\_CHANGE\_NOTIFICATION\_METHOD |

</details>

<details>

<summary>Others</summary>

| Event                  | Enum Value                              |
| ---------------------- | --------------------------------------- |
| General authentication | APP\_AUTHENTICATION\_DEFAULT            |
| Making a payment       | APP\_PAYMENT\_DEFAULT                   |
| Password Change        | APP\_ACCOUNT\_PASSWORD\_CHANGE\_DEFAULT |
| Password Reset         | APP\_ACCOUNT\_PASSWORD\_RESET\_DEFAULT  |
| Account Details Change | APP\_ACCOUNT\_DETAILS\_CHANGE\_DEFAULT  |
| App onboarding         | APP\_ONBOARDING\_DEFAULT                |

</details>

### Response

#### Successful Response

If the request was successful, you will receive a response in JSON format which contains the following parameters:

| Parameter     | Description                                                                                                 | Data type                                   |
| ------------- | ----------------------------------------------------------------------------------------------------------- | ------------------------------------------- |
| `request_uri` | This is a reference to the payload that you have sent in this request. This will be needed in the next step | String                                      |
| `expires_in`  | This is a number, in seconds, representing the lifetime of the `request_uri`                                | Number. We set this value to be 60 seconds. |

<details>

<summary>Sample successful response body</summary>

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

</details>

#### Error Response

If there was a problem with the request, you will receive a response in JSON format which will instead contain these parameters:

<table><thead><tr><th width="164.765625">Parameter</th><th width="404.29296875">Description</th><th>Data type</th></tr></thead><tbody><tr><td><code>error</code></td><td>An error code identifying the type of error that has occurred.</td><td>This will be an enum value. The possible values are detailed <a href="#possible-error-values">below</a>.</td></tr><tr><td><code>error_description</code></td><td>A human-readable text description of the error.</td><td>String. This is optional.</td></tr><tr><td><code>error_uri</code></td><td>URI of a web page that includes additional information about the error</td><td>URL. This is optional.</td></tr><tr><td><code>state</code></td><td>This will be the same state parameter passed in the authorization request.</td><td>A string with a maximum length of 255 characters. It must match the regular expression pattern <code>[A-Za-z0-9/+_-=.]+</code></td></tr></tbody></table>

<details>

<summary>Sample error response body</summary>

```json
{
  "error": "invalid_request",
  "error_description": "The request is missing a required parameter, includes an unsupported value, or is malformed.",
  "state": "e32b9f28-5d34-4c0f-8b0e-6b670566c97f"
}
```

</details>

#### Possible error values

The table below lists the possible values of `error` that we may return:

<table><thead><tr><th width="237.33203125">error</th><th>What this error indicates</th></tr></thead><tbody><tr><td><code>invalid_request</code></td><td>The request had missing or invalid parameters. You should ensure that all the parameters follow the specifications listed above. This error will also be returned if you did not send either the <code>DPoP</code> header or the <code>dpop_jkt</code> parameter.</td></tr><tr><td><code>invalid_client</code></td><td><p>This error may occur if your client assertion could not be verified. This is most commonly caused by a malformed JWKS, or an incorrectly generated client assertion.</p><p>Refer to our guides on <a href="../technical-concepts/generation-of-client-assertion">client assertions</a> and <a href="../technical-concepts/json-web-key-sets-jwks">JWKS</a>, and make sure that your implementation follows both of these guides.<br><br>This can also be caused by an invalid <code>client_id</code> being passed. Check that your <code>client_id</code> is correct, and that your app is currently active.</p></td></tr><tr><td><code>invalid_scope</code></td><td>The <code>scope</code> parameter that you have provided is invalid. This is typically caused if you did not include the <code>openid</code> scope, or if you are requesting for a scope which your app is not allowed to request.<br><br>If requesting for a new scope, you will need to <a href="../../singpass-developer-portal-sdp/user-guide/edit-production-app">edit your app</a> and add the new scope into the list of your app's allowed scopes.</td></tr><tr><td><code>invalid_dpop_proof</code></td><td>The <code>DPoP</code> header which you have provided is invalid, expired, or malformed. Read our <a href="../technical-concepts/demonstrating-proof-of-possession-dpop">DPoP guide</a> and ensure that your implementation follows the instructions in the guide.</td></tr><tr><td><code>server_error</code></td><td><p>The server encountered an unexpected error. You should check <code>error_description</code> to understand what was the cause of the error.</p><p>This error can potentially be caused by your JWKS endpoint not being reachable. Read our guide on <a href="../../technical-concepts/json-web-key-sets-jwks#requirements-for-jwks">JWKS</a> and ensure that you follow the requirements. In particular, your JWKS endpoint must be publicly accessible and should respond in a timely manner.</p><p>If the cause was not your JWKS endpoint, you may perform up to 3 retries using an exponential backoff strategy. If the request still fails, you should guide users to alternative authentication methods.</p></td></tr><tr><td><code>temporarily_unavailable</code></td><td>The server is temporarily unavailable to handle the request. You may perform up to 3 retries using an exponential backoff strategy. If the request still fails, you should guide users to alternative authentication methods, or to guide them to try again some time later.</td></tr></tbody></table>

## 2. Redirecting the user to the authorization URL

After you complete the pushed authorization request, the next step is to redirect the user to open the authorization URL in their browser.

The base URL for the authorization URL can be located as the `authorization_endpoint` field in our authorization server's [OpenID Configuration](https://docs.developer.singpass.gov.sg/docs/technical-specifications/technical-concepts/openid-connect-discovery). You will only need to attach two query parameters to the authorization endpoint to form the authorization URL:

| Parameter     | Description                                                                                                                                                                                                                                                                      |
| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `client_id`   | <p>The client ID of your registered client, provided by Singpass during app onboarding. It is the App ID found at the top of your app configuration page.<br></p><p>This must be the same client ID that you passed in the request body of the pushed authorization request.</p> |
| `request_uri` | The `request_uri` returned by the pushed authorization request.                                                                                                                                                                                                                  |

Once you have redirected the user to the authorization URL, the next step would be to wait for the user to complete authentication. Once they complete authentication, they will be redirected back to the `redirect_uri` that you specified. View the next page to understand how to handle the redirect.

<details>

<summary>Sample authorization URL</summary>

{% code overflow="wrap" %}

```url
https://id.singpass.gov.sg/fapi/auth?client_id=T5sM5a53Yaw3URyDEv2y9129CbElCN2F&request_uri=urn:ietf:params:oauth:request_uri:Tku8lLFs7d_UPZznhREj0
```

{% endcode %}

</details>
