1. Authorization Request

The first step in the Singpass authentication flow involves redirecting users to the Singpass login page. As Singpass requires the use of Pushed Authorization Requests (as defined in RFC 9126), you will need to perform two steps to do this:

  1. Send a POST request to the pushed_authorization_request_endpoint defined in our authorization server's OpenID configuration.

  2. Construct the authorization URL, and redirect the user to this URL.

We require Pushed Authorization Requests as a security measure to prevent request parameters from being tampered by malicious parties.

More details about these 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.

Parameter
Description
Data type

response_type

The authorization processing flow to be used.

Only the value code is supported, as mandated by FAPI2.0 specifications.

scope

A space-delimited string, representing a list of scopes that you are requesting.

The scopes that you request will determine the data that is returned in the ID token and in the userinfo endpoint. For Login apps, the only supported scopes are openid and sub_account.

A space-delimited string representing a list of scopes. See our Data Catalog for the allowed values.

The openid scope must be specified, as per the OIDC specifications. In addition to the scopes listed in the Data Catalog, the sub_account scope is also supported. See Parsing the ID token for more details.

state

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.

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. 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.

A string with a maximum length of 255 characters. It must match the regular expression pattern [A-Za-z0-9/+_-=.]+.

nonce

A session-based, unique, and non-guessable value that you should generate per auth session. This is used to mitigate replay attacks.

Just like the state 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. 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.

A string with a maximum length of 255 characters.

We recommend using a randomly-generated version 4 UUID for this purpose.

client_id

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

A 32-character case-sensitive alphanumeric string.

redirect_uri

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.

URL

acr_values

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. Should multiple values be provided, we will use the first available level of assurance for the authentication.

Optional. The possible values are:

  • urn:singpass:authentication:loa:2

    • This refers to an assurance level of 2, meaning that only 2FA is required

  • urn:singpass:authentication:loa:3

    • 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.

client_assertion_type

The type of client assertion.

Must be the string urn:ietf:params:oauth:client-assertion-type:jwt-bearer, as mandated by OIDC specifications.

client_assertion

Your client assertion, which is used for authentication. Refer to Generation of Client Assertion for instructions on how this should be generated.

A string containing the signed JWT.

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 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 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.

Parameter
Description
Data Type

authentication_context_type

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.

Mandatory for Login apps, and not allowed for Myinfo (v5) apps.

The list of possible values is provided below.

authentication_context_message

A string value providing context on what users are performing authentication for. This will be displayed to users when they are performing authentication.

String. Optional, and allowed only for Login apps.

redirect_uri_https_type

This value describes the type of redirect that you intend to perform. You should specify this as app_claimed_https if you are performing a redirection to a mobile app via an App-claimed https URL.

Either app_claimed_https or standard_https.

This field is optional; it defaults to standard_https if not provided.

app_launch_url

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.

Optional. This should be an iOS App Link.

Sample request
POST /par HTTP/1.1
Content-Type: application/x-www-form-urlencoded
DPoP: eyJhbGciOiJFUzI1NiIsInR5cCI6ImRwb3Arand0IiwiandrIjp7Imt0eSI6IkVDIiwiY3J2IjoiUC0yNTYiLCJ4IjoiQXNWakh4elZ4MURaNnNKcEpzUnM2ek5YYXFmcFR3UmNfcXV0bWw0aEFJQSIsInkiOiI0SkhwVVZDRE5DaXhOTW9OclIzSElodFRzTWNfMF9NcmdpMzJxR3VoUkQ4In19.eyJqdGkiOiIyZmM3Y2Q4ZC0xN2IzLTRlYTUtYTg4ZC1lZWM0NTY5M2JjZmUiLCJodG0iOiJQT1NUIiwiaHR1IjoiaHR0cHM6Ly9hcGkuZXhhbXBsZS5jb20vZGF0YSIsImlhdCI6MTc1NjcwODI0N30.wBYjFQRzY2o5aG82LjR1X8qT9bZ-jK3c7hI5fE0gP9vR_7sU6tW5xV4yZ3aB2cE1dF0eG9hI8jJ7kL6mN5oP4qR
Host: id.singpass.gov.sg

scope=openid%20sub_account&response_type=code&redirect_uri=https%3A%2F%2Fpartner.gov.sg%2Fredirect&nonce=bb5e1672-a460-4a9b-874e-c38d55ac3922&client_id=T5sM5a53Yaw3URyDEv2y9129CbElCN2F&state=e32b9f28-5d34-4c0f-8b0e-6b670566c97f&code_challenge=MmEbVJBa0kLYEjPAj6p7bSwEc0qy7UPFPQDU-Soltwo&code_challenge_method=S256&transaction_category=authentication&auth_context_message=update%20your%20account%20details

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.

CPF transactions
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

Banking
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

Other Financial Institutions
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

Telcos
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

Others
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

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. Maximum allowed value is 600

Sample successful response body
{
  "request_uri": "7214b93e-0b60-4a05-8421-5b169a0ea3f0",
  "expires_in": 300
}

Error Response

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

Parameter
Description
Data type

error

An error code identifying the type of error that has occurred.

This will be an enum value. The possible values are detailed below.

error_description

A human-readable text description of the error.

String. This is optional.

error_uri

URI of a web page that includes additional information about the error

URL. This is optional.

state

This will be the same state parameter passed in the authorization request.

A string with a maximum length of 255 characters. It must match the regular expression pattern [A-Za-z0-9/+_-=.]+

Sample error response body
{
  "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"
}

Possible error values

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

error
What this error indicates

invalid_request

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 DPoP header or the dpop_jkt parameter.

invalid_client

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.

Refer to our guides on client assertions and JWKS, and make sure that your implementation follows both of these guides. This can also be caused by an invalid client_id being passed. Check that your client_id is correct, and that your app is currently active.

invalid_scope

The scope parameter that you have provided is invalid. This is typically caused if you did not include the openid scope, or if you are requesting for a scope which your app is not allowed to request. If requesting for a new scope, you will need to edit your app and add the new scope into the list of your app's allowed scopes.

invalid_dpop_proof

The DPoP header which you have provided is invalid, expired, or malformed. Read our DPoP guide and ensure that your implementation follows the instructions in the guide.

server_error

The server encountered an unexpected error. You should check error_description to understand what was the cause of the error.

This error can potentially be caused by your JWKS endpoint not being reachable. Read our guide on JWKS and ensure that you follow the requirements. In particular, your JWKS endpoint must be publicly accessible and should respond in a timely manner.

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.

temporarily_unavailable

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.

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 the authorization server metadata. You will only need to attach two query parameters to the authorization endpoint to form the authorization URL:

Parameter
Description

client_id

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.

This must be the same client ID that you passed in the request body of the pushed authorization request.

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.

Sample authorization URL
https://id.singpass.gov.sg/auth?client_id=T5sM5a53Yaw3URyDEv2y9129CbElCN2F&request_uri=7214b93e-0b60-4a05-8421-5b169a0ea3f0

Last updated

Was this helpful?