Singpass Developer Docs
Developer Docs for Singpass
Developer Docs for Singpass
  • INTRODUCTION
    • Overview of Singpass
    • Understanding the basics of OIDC
  • Products
    • Login
      • Introduction
      • Key Principles
      • User Journey
      • Logo Download and Brand Guidelines
      • Singpass Button Guidelines (For developers and designers)
    • FAQ
      • Login
      • Myinfo
    • Myinfo
      • Introduction
      • Key Principles
      • User Journey
      • Logo Download and Brand Guidelines
      • Data Display Guidelines
      • Scheduled Downtimes
  • GETTING STARTED
    • Onboarding Checklist
    • User Journey
    • Create Singpass Application
    • Start Integration - Demo App
  • Technical Specifications
    • Singpass Authentication API
      • Overview of Singpass Flow
      • 1. Authorization Endpoint
        • Redirection on success
        • For Mobile Developers
      • 2. Token Endpoint
        • Authorization Code Grant
        • Client JWK Requirements
      • 3. Userinfo Endpoint
        • Requesting Userinfo
        • Validating the payload
      • .well-known Endpoints
        • OpenID Discovery Endpoint
        • JWKS Endpoint
      • Error Response
      • Frame busting for web views
    • Staging and Production URLs
  • Singpass Developer Portal (SDP)
    • User Guide
      • Obtain Access to SDP
      • Login to SDP
      • Toggle Staging vs Production
      • Create Staging App
      • Edit Staging App
      • Create Staging Test Account
      • Create Production App
      • Edit Production App
      • Consent to Singpass Service Agreement
      • View Singpass Service Agreement
      • Updating Billing Contact Information
      • Deactivate Production App
      • Activate Production App
      • How to View Production App Transactions
    • Understanding the App Config Fields
      • App Name
      • App Description
      • Site URL
      • Support Emails
      • Allowed Scopes
      • Redirect URL
      • Token-based Authentication
  • Data Catalog (Myinfo)
    • Understanding the Data
      • Local Registered Birth Records and Sponsored Child Records
      • CPF Contribution History (up to 15 months)
      • Notice of Assessment (Basic)
      • Notice of Assessment (Detailed)
    • Catalog
      • Personal
      • Finance
      • Education and Employment
      • Family
      • Vehicle and Driving Licence
      • Property
      • Government Scheme
  • TESTING
    • Testing with Singpass App
    • Myinfo Test Personas
  • MORE INFORMATION
    • Contact
Powered by GitBook
On this page
  • Client Authentication - Client Assertion JWT
  • Assertion JWT Structure
  • Request / Response Structure
  • Error Response
  • ID Token Structure
  • Overview of a JWS in JWE
  • JWE Header
  • Overview of JWS
  • JWS Header
  • JWS Claims

Was this helpful?

  1. Technical Specifications
  2. Singpass Authentication API
  3. 2. Token Endpoint

Authorization Code Grant

Client Authentication - Client Assertion JWT

Assertion JWT Structure

The RP is required to generate an assertion JWT that has the following header and claims, and is signed with the JWK that was provided during onboarding.

JWT Header

The header must include alg and typ.

The supported alg types are:

  • ES256

  • ES384

  • ES512.

This must match the alg value in the signing key used to sign the assertion (if the signing JWK specifies alg explicitly).

The header should also include kid of the signing key to help identify which of the RP’s signing keys was used, though this is not mandatory. If omitted, we will test against all known signing keys when attempting to verify the signature.

example

{
  "typ" : "JWT",
  "alg" : "ES256",
  "kid" : "rp_key_01"
}

JWT Claims

Path
Type
Description

sub

String

This should be client_id of the registered client.

aud

String

iss

String

This should be client_id of the registered client.

iat

Number

exp

Number

code

String

(Optional) This should be the auth code which is used to exchange for an ID token. It should be identical to the code form param sent outside the client_assertion. This enables increased security by signing the code so that the client_assertion can only be used once for a specific request.

Request / Response Structure

Curl request

$ curl 'https://stg-id.singpass.gov.sg/token' -i -X POST \
    -H 'Content-Type: application/x-www-form-urlencoded; charset=ISO-8859-1' \
    -d 'grant_type=authorization_code&redirect_uri=http%3A%2F%2Fexample.com&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&client_assertion=eyJraWQiOiJycF9rZXlfMDEiLCJ0eXAiOiJKV1QiLCJhbGciOiJFUzM4NCJ9.eyJzdWIiOiJnblk2RXJpY2hwYjV0NE5GUlA5UjRMN2FFQzlOMEZRSCIsImF1ZCI6Imh0dHBzOi8vc3RnLWlkLnNpbmdwYXNzLmdvdi5zZyIsImNvZGUiOiJuMGVzYzNOUnplN0xUQ3U3aVl6UzZhNWFjYzNmMG9ncDQiLCJpc3MiOiJodHRwOi8vZXhhbXBsZS5jb20iLCJleHAiOjE3MjczMjIwNjUsImlhdCI6MTcyNzMyMTk0NX0.AAAAAAAAAAAAAAAAAAAAAIvHG8uapa4w10pPn_S_7uyYPXNJWU7389sTLNHXrCKhAAAAAAAAAAAAAAAAAAAAAIxyKbbZfLSkduU6WIPrrPe1kGvmHmzXL4PHpgAJ0g0d&code=n0esc3NRze7LTCu7iYzS6a5acc3f0ogp4&client_id=gnY6Erichpb5t4NFRP9R4L7aEC9N0FQH&code_verifier=mN7szCmmIc6Z2Vg-iaX7f7RDVsKAhY5GG-r7Crq0jxTdxY0xyPKnsAEWtEMdZ3D8QW5rs-C824W3Jwntcw'

Form parameters

Parameter
Description

client_id

The Client Identifier registered.

redirect_uri

The redirect URI being used in this auth session.

grant_type

The type of grant being requested. This must be set to authorization_code.

code

The code issued earlier in the auth session.

scope

(Optional) If no value is provided, it defaults to openid. If provided, then only openid is allowed.

client_assertion_type

This MUST be set to urn:ietf:params:oauth:client-assertion-type:jwt-bearer.

client_assertion

A JWT identifying the client.

code_verifier

(Mandatory) This is the session-based, unique, and non-guessable value that the RP had used to generate the code_challenge.

Must match regexp pattern of [a-zA-Z0-9_\-.~]+ minimum length of 43 characters and a maximum length of 128 characters.

HTTP request

POST /token HTTP/1.1
Content-Type: application/x-www-form-urlencoded; charset=ISO-8859-1
Host: stg-id.singpass.gov.sg
Content-Length: 788

grant_type=authorization_code&redirect_uri=http%3A%2F%2Fexample.com&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&client_assertion=eyJraWQiOiJycF9rZXlfMDEiLCJ0eXAiOiJKV1QiLCJhbGciOiJFUzM4NCJ9.eyJzdWIiOiJnblk2RXJpY2hwYjV0NE5GUlA5UjRMN2FFQzlOMEZRSCIsImF1ZCI6Imh0dHBzOi8vc3RnLWlkLnNpbmdwYXNzLmdvdi5zZyIsImNvZGUiOiJuMGVzYzNOUnplN0xUQ3U3aVl6UzZhNWFjYzNmMG9ncDQiLCJpc3MiOiJodHRwOi8vZXhhbXBsZS5jb20iLCJleHAiOjE3MjczMjIwNjUsImlhdCI6MTcyNzMyMTk0NX0.AAAAAAAAAAAAAAAAAAAAAIvHG8uapa4w10pPn_S_7uyYPXNJWU7389sTLNHXrCKhAAAAAAAAAAAAAAAAAAAAAIxyKbbZfLSkduU6WIPrrPe1kGvmHmzXL4PHpgAJ0g0d&code=n0esc3NRze7LTCu7iYzS6a5acc3f0ogp4&client_id=gnY6Erichpb5t4NFRP9R4L7aEC9N0FQH&code_verifier=mN7szCmmIc6Z2Vg-iaX7f7RDVsKAhY5GG-r7Crq0jxTdxY0xyPKnsAEWtEMdZ3D8QW5rs-C824W3Jwntcw

HTTP response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
x-ndi-response-category: client-assertion-auth-code
X-XSS-Protection: 0
X-Frame-Options: DENY
Date: Thu, 26 Sep 2024 03:39:05 GMT
Connection: keep-alive
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
X-Content-Type-Options: nosniff
Transfer-Encoding: chunked
Content-Type: application/json
Content-Length: 597

{
  "access_token" : "Ul5JqK8vJX8Jfgo7UjpiIigF7DciW7YGnUACLN1/T80=",
  "token_type" : "Bearer",
  "id_token" : "eyJraWQiOiJuZGlfc3RnXzAxIiwidHlwIjoiSldUIiwiYWxnIjoiRVMyNTYifQ.eyJhdWQiOiJnblk2RXJpY2hwYjV0NE5GUlA5UjRMN2FFQzlOMEZRSCIsInN1YiI6InM9Uzg4MjkzMTRCLHU9MWMwY2VlMzgtM2E4Zi00ZjhhLTgzYmMtN2EwZTRjNTlkNmE5IiwiYW1yIjpbInB3ZCIsInN3ayJdLCJpc3MiOiJodHRwczovL3N0Zy1pZC5zaW5ncGFzcy5nb3Yuc2ciLCJleHAiOjE3MjczMjI1NDUsImlhdCI6MTcyNzMyMTk0NSwibm9uY2UiOiJMNW5tUWZjZXREREllaW5jb3F2Q3JGeUd2K25Ib2JrdjRYb2NOWVBDWGFRPSJ9.bD1osnkuL-hXCXY9L_LbveANix_tBsjk8872bL04tTPFGMkzMjE85W8fTwQXrPSFnwQtgzmLB2__i0vdGYnfgA"
}

Request body

grant_type=authorization_code&redirect_uri=http%3A%2F%2Fexample.com&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&client_assertion=eyJraWQiOiJycF9rZXlfMDEiLCJ0eXAiOiJKV1QiLCJhbGciOiJFUzM4NCJ9.eyJzdWIiOiJnblk2RXJpY2hwYjV0NE5GUlA5UjRMN2FFQzlOMEZRSCIsImF1ZCI6Imh0dHBzOi8vc3RnLWlkLnNpbmdwYXNzLmdvdi5zZyIsImNvZGUiOiJuMGVzYzNOUnplN0xUQ3U3aVl6UzZhNWFjYzNmMG9ncDQiLCJpc3MiOiJodHRwOi8vZXhhbXBsZS5jb20iLCJleHAiOjE3MjczMjIwNjUsImlhdCI6MTcyNzMyMTk0NX0.AAAAAAAAAAAAAAAAAAAAAIvHG8uapa4w10pPn_S_7uyYPXNJWU7389sTLNHXrCKhAAAAAAAAAAAAAAAAAAAAAIxyKbbZfLSkduU6WIPrrPe1kGvmHmzXL4PHpgAJ0g0d&code=n0esc3NRze7LTCu7iYzS6a5acc3f0ogp4&client_id=gnY6Erichpb5t4NFRP9R4L7aEC9N0FQH&code_verifier=mN7szCmmIc6Z2Vg-iaX7f7RDVsKAhY5GG-r7Crq0jxTdxY0xyPKnsAEWtEMdZ3D8QW5rs-C824W3Jwntcw

Response body

{
  "access_token" : "Ul5JqK8vJX8Jfgo7UjpiIigF7DciW7YGnUACLN1/T80=",
  "token_type" : "Bearer",
  "id_token" : "eyJraWQiOiJuZGlfc3RnXzAxIiwidHlwIjoiSldUIiwiYWxnIjoiRVMyNTYifQ.eyJhdWQiOiJnblk2RXJpY2hwYjV0NE5GUlA5UjRMN2FFQzlOMEZRSCIsInN1YiI6InM9Uzg4MjkzMTRCLHU9MWMwY2VlMzgtM2E4Zi00ZjhhLTgzYmMtN2EwZTRjNTlkNmE5IiwiYW1yIjpbInB3ZCIsInN3ayJdLCJpc3MiOiJodHRwczovL3N0Zy1pZC5zaW5ncGFzcy5nb3Yuc2ciLCJleHAiOjE3MjczMjI1NDUsImlhdCI6MTcyNzMyMTk0NSwibm9uY2UiOiJMNW5tUWZjZXREREllaW5jb3F2Q3JGeUd2K25Ib2JrdjRYb2NOWVBDWGFRPSJ9.bD1osnkuL-hXCXY9L_LbveANix_tBsjk8872bL04tTPFGMkzMjE85W8fTwQXrPSFnwQtgzmLB2__i0vdGYnfgA"
}

Response fields

Path
Type
Description

access_token

String

For Login flows, the access token will be a random string that is not to be used. For Myinfo flows, the token will be an encoded JSON Web Token (JWT). This token is to be used to exchange for payload at UserInfo Endpoint.

token_type

String

The type of token being requested, Bearer only so far.

id_token

String

Error Response

ID Token Structure

The format and structure of the issued ID Token will vary depending on the client’s profile as specified in this table below:

Client Profile

sub Claim Content

ID token format

direct

UUID only (eg. u=32af8b7d-ad1d-4c25-8dc7-0a981b533000)

JWS

direct_pii_allowed

Regular NRIC holders: NRIC and UUID (eg. s=S1234567A,u=32af8b7d-ad1d-4c25-8dc7-0a981b533000)

Singpass Foreign Account (SFA) holders: Singpass User ID (UID), Foreigner ID (FID), Country-of-Issuance (COI) and UUID (eg. s=Y7613265T,fid=G730Z-H5P96,coi=DE,u=e2af740e-25b4-4b19-b527-494670952cb0)

This class of users were previously known as "Foreign Unique Account" or "Singpass Foreign Unique Account" users. Only designated relying parties are able to have SFA users authenticate & complete token exchange.

JWS in JWE (encrypted with client’s JWK)

See section below for more details about the JWE format.

bridge (special case internal use only)

NRIC and UUID (eg. s=S1234567A,u=32af8b7d-ad1d-4c25-8dc7-0a981b533000)

JWS

Overview of a JWS in JWE

An encrypted ID token will returned from the /token endpoint is a JWS in JWE that is in compact serialization form. It has the following structure:

  • JWE Header

  • Encrypted Key

  • Initialization Vector

  • Authentication Tag

JWE Header

Note: Relying parties should use the kid field in the header to determine which key NDI used for encryption.

example

{
	"kid": "client_01",
	"cty": "JWT",
	"enc": "A256CBC-HS512",
	"alg": "ECDH-ES+A256KW"
}

Overview of JWS

  • JWS Header

  • Payload (containing claims)

  • Signature

JWS Header

example

{
  "kid" : "ndi_stg_01",
  "typ" : "JWT",
  "alg" : "ES256"
}

JWS Claims

The JWS ID token will contain the following claims.

example

{
  "aud" : "gnY6Erichpb5t4NFRP9R4L7aEC9N0FQH",
  "sub" : "s=S8829314B,u=1c0cee38-3a8f-4f8a-83bc-7a0e4c59d6a9",
  "amr" : [ "pwd", "swk" ],
  "iss" : "https://stg-id.singpass.gov.sg",
  "exp" : 1727322545,
  "iat" : 1727321945,
  "nonce" : "L5nmQfcetDDIeincoqvCrFyGv+nHobkv4XocNYPCXaQ="
}

Table 1. Description of Claims

Path
Type
Description

sub

String

aud

String

iss

String

iat

Number

exp

Number

amr

Array

Authentication method references. Example values are ["face"], ["fv"], ["fv-alt"], ["otp"], ["pwd","fv"], ["pwd","otp-email"], ["pwd","sms"], ["pwd","swk"], ["pwd"], ["sso"]. Note that this list is non-exhaustive, and NDI reserves the right to introduce new values without prior notice to RPs.

nonce

String

acr

String

(Optional) The Authentication Context Class Reference. The values are context-specific and agreed upon between NDI and relying parties when used.

Previous2. Token EndpointNextClient JWK Requirements

Last updated 21 days ago

Was this helpful?

The recipient that the JWT is intended for. This must match the issuer field in the response of the OpenID discovery endpoint () e.g. .

The time at which the JWT was issued.

The expiration time on or after which the JWT MUST NOT be accepted by Singpass for processing. Additionally, Singpass will not accept tokens with an exp longer than 2 minutes since iat.

The ID token with relevant claims in JWT format signed by the ASP. Note that the example response body shows a JWS (3-part structure separated by dots), but the format will differ for a JWS in JWE (5-part structure). Refer for more details about the ID token structure.

Singpass generally follows OIDC error response specifications. For more information, please refer to .

Encrypted Payload (if decrypted, this would be the Base64 encoded form of a )

See for more details.

The JWE will contain these standard headers. Refer to for more information about each header.

The ID token returned from the /token endpoint is in compact serialization form. A JWS has the following structure.

The JWS ID token will contain these standard headers. Refer to for more information about each header.

The principal that is the subject of the JWT. Contains a comma-separated, key=value mapping that identifies the user; possibly including multiple alternate IDs representing the user. The keys included vary by the profile of the OIDC client, and the user type, however the minimal format is u=<UUID> where UUID represents the user’s globally unique identifier.

The client_id of the relying party.

The principal that issued the JWT.

The time at which the JWT was issued.

The expiration time on or after which the JWT MUST NOT be accepted for processing. Defaults to 10 minutes since "iat".

String value used to associate a Client session with an ID Token, and to mitigate replay attacks. The value is passed through unmodified from the Authentication Request to the ID Token. Clients MUST verify that the nonce Claim Value is equal to the value of the nonce parameter sent in the Authentication Request.

Token Error Response specifications
https://datatracker.ietf.org/doc/html/rfc7516#section-3.1
https://tools.ietf.org/html/rfc7515#section-4
JWS
https://tools.ietf.org/html/rfc7515#section-4
JWS ID Token
https://id.singpass.gov.sg/.well-known/openid-configuration
https://id.singpass.gov.sg
https://tools.ietf.org/html/rfc7519#section-4.1.6
https://tools.ietf.org/html/rfc7519#section-4.1.4
https://tools.ietf.org/html/rfc7519#section-4.1.2
https://tools.ietf.org/html/rfc7519#section-4.1.3
https://tools.ietf.org/html/rfc7519#section-4.1.1
https://tools.ietf.org/html/rfc7519#section-4.1.6
https://tools.ietf.org/html/rfc7519#section-4.1.4
https://openid.net/specs/openid-connect-core-1_0.html#IDToken
here