Token Endpoint
Endpoint to obtain an ID token. The ID token is a signed JWT that contains user information in the sub claim, and is signed by Singpass Auth. RPs will be able to verify the ID token’s JWT signature with our JWKS endpoint.
For the Step-up authentication flow, only the following grant(s) is supported:
urn:openid:params:grant-type:ciba
In the below sections, we are going to describe the API contract.
Client-Initiated Backchannel Authentication (CIBA) Grant
This grant type allows the RP to obtain an ID token for the user indicated by the login_hint
parameter that was provided during initiation. This is only allowed for confidential
RPs.
Currently, Singpass only supports Poll mode, which means that RPs need to poll the token endpoint at regular intervals until they receive an ID token or receive certain error codes (see Error Responses).
Important
RPs should NOT send two overlapping token requests with the same auth_req_id
. RPs should always wait until receiving the response to the previous request before sending out the next request.
Note
It is recommended for RPs to wait for at least 30s for a response before trying again.
Client Authentication - Client Assertion JWT
RPs must authenticate themselves using Client Assertion JWT.
In this authentication mechanism, the RP is required to present an assertion JWT in the request body. Singpass will then verify this JWT against a JWK provided by the RP during onboarding.
This method of authentication relies on PKI and eradicates the need to keep and transfer secrets. You may refer to this RFC spec documentation for more details.
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
JWT Claims
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
Request / Response Structure
Curl request
Form parameters
auth_req_id
Authentication request id.
grant_type
The type of grant being requested. This must be set to urn:openid:params:grant-type:ciba
.
client_assertion_type
This MUST be set to urn:ietf:params:oauth:client-assertion-type:jwt-bearer
client_assertion
A JWT identifying the client.
HTTP request
HTTP response
Request body
Response body
Response fields
token_type
String
The type of token being requested, Bearer only so far.
id_token
String
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). See below for more details about the ID token structure.
Error Responses
The table below shows the list of common error codes that may be returned for this endpoint. RPs must take note to only re-poll the token endpoint for scenarios as specified below.
Important
Note that only the error
field in the JSON response should be used to determine the error scenario. Do NOT use the error_description
field to determine the error scenario. Singpass reserves the right to change the content of the error_description
field without prior notice to RPs.
Error code (returned in error
field)
Error scenario
Can perform re-poll?
authorization_pending
The session is still pending as the end-user has not authenticated yet.
Yes
access_denied
End-user rejected the authentication via SP mobile app.
No
expired_token
The authentication session has expired or is not found.
No
unauthorized_client
RP is not authorized to perform this flow.
No
invalid_client
RP failed client assertion authentication.
No
invalid_grant
-
No
invalid_request
-
No
server_error
-
No
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
Encrypted Payload (if decrypted, this would be the Base64 encoded form of a JWS ID Token)
Authentication Tag
See https://datatracker.ietf.org/doc/html/rfc7516#section-3.1 for more details.
JWE Header
The JWE will contain these standard headers. Refer to https://tools.ietf.org/html/rfc7515#section-4 for more information about each header.
Note: Relying parties should use the kid
field in the header to determine which key Singpass used for encryption.
example
Overview of a JWS
The JWS ID token returned from the /token
endpoint is in compact serialization form. A JWS has the following structure.
JWS Header
Payload (containing claims)
Signature
JWS Header
The JWS ID token will contain these standard headers. Refer to https://tools.ietf.org/html/rfc7515#section-4 for more information about each header.
example
JWT Claims
The JWS ID token will contain the following claims.
example
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 Singpass reserves the right to introduce new values without prior notice to RPs.
Client JWK Requirements
Clients are expected to provide public keys to Singpass in the JWK format. These public keys will be used in the following (non-exhaustive) scenarios:
Signature JWK used to verify the signature of the client assertion JWT presented during token request.
Encryption JWK used to encrypt an ID token which contains the user’s PII.
The client must provide the public key(s) during onboarding, and they can do so only via ONE of the following forms:
Provide a JWKS in a JSON format.
Host the JWKS on a publicly accessible URL. This endpoint must be compatible with Singpass' service level expectations.
Signing key is always required for both direct
and direct_pii_allowed
clients. Encryption key is only required for direct_pii_allowed
clients. direct_pii_allowed
clients must ensure that the provided JWKS or the resource returned by the JWKS URL contains both the signing and encryption keys.
Tip
JWK for signing
The signing JWK will be used to verify the client assertion JWT provided during /token
request, thereby authenticating the client.
Clients are allowed to provide multiple signature keys in the JWKS / hosted on the JWKS url provided during client creation.
The signature JWK should have the following attributes:
Must have key
use
of valuesig
per rfc7517#section-4.2Must contain a key ID in the standard
kid
field per rfc7517#section-4.5Will be used by Singpass to select the relevant key to verify the client assertion
Must be an EC key, with curves:
P-256
,P-384
orP-521
(NIST curves, akasecp256r1
,secp384r1
,secp521r1
respectively)
Example EC signing key using P-256 and a timestamped key Id
Key Rotation
Relying parties can rotate their signing keys in a self-driven manner. To do this with zero downtime the Relying party must
support use of JWKS URLs and be onboarded as such
ensure their replacement signing key has a different key ID (
kid
) to the original keyensure their replacement signing key matches the other cryptographic key requirements
To do this with zero downtime, the following procedure should be followed by the Relying Party:
Prep
Relying party generates a new signing key pair (K2
) supported for signing.
T0
Relying party adds public key K2
to its JWKS endpoint (and leaves K1
on the endpoint)
T0 - T+1 hour
Singpass' cache will expire, and re-retrieves the relying party’s published keys from their JWKS endpoint which now includes K2
> T+1 hour
Relying party changes their system to start signing client assertions using the new signing key K2
Clean Up
Post-validation, relying party can remove key K1
from their JWKS endpoint when they are comfortable their new signing key is working
JWK for encryption
The encryption JWK will be used to encrypt ID tokens requested from the /token
endpoint.
Singpass will select the strongest available, supported encryption key from either a local JWKS, or JWKS URL to encrypt returned ID tokens for those relying parties who require any PII in the ID token.
The encryption JWK must have the following attributes:
Must have key
use
of valueenc
per rfc7517#section-4.2Must contain a key ID in the standard
kid
field per rfc7517#section-4.5The key ID will be specified in the returned JWE header so that clients can pick the right key for decryption
Must have key type (
kty
) ofEC
Must specify the appropriate key encryption
alg
the relying party wants Singpass to use, consistent with the key type/curve (kty
), and meet the requirements below on allowedalg
/curve
/key sizes, consistent with RFC7518 - JSON Web Algorithm specification
Key Type (kty
)
EC
Status
Required for new Relying Parties
Key encryption algorithm (alg
)
ECDH-ES+A128KW ECDH-ES+A192KW ECDH-ES+A256KW
Curve (crv
)
P-256 (NIST, aka secp256r1) P-384 (NIST, aka secp384r1) P-521 (NIST, aka secp521r1)
Example EC encryption key using P-256 and a timestamped key Id; asking us to encrypt the CEK using ECDH-ES+A128KW
Key Preference
If the relying party exposes multiple supported encryption keys, Singpass will select the key to use for encrypting tokens based on the following logic:
prefer any EC key (
kty
) matching the above requirementsprefer EC keys with stronger
crv
(curve) above EC keys with weaker curveprefer EC keys with stronger
alg
key wrapping above weaker onesotherwise pick the first compatible key we find
Key Rotation
Relying parties can rotate their encryption keys in a self-driven manner. To do this with zero downtime the Relying party must
support use of JWKS URLs and be onboarded as such
have the ability to decrypt tokens produced with either one of two different encryption keys based on either
selecting the correct decryption key by its key ID (
kid
)trial-and-error decryption against multiple keys in a collection
ensure their replacement key matches the other cryptographic key requirements noted above
To do this with zero downtime, the following procedure should be followed by the Relying Party:
Prep
Relying party generates a new encryption key pair (K2
) supported for decryption. The existing key pair (K1
) is still available for decryption of ID tokens
T0
Relying party removes public key K1
and adds public key K2
on its JWKS endpoint
T0 - T+1 hour
Singpass' caches will expire at any (indeterminate) time within this period, and start encrypting tokens with new encryption key K2
.
T0 - T+1 hour
Relying party may be receiving tokens encrypted with either K1
or K2
keys throughout this period; and must be able to decrypt either.
> T+1 hour
Relying party can remove support for decrypting with the previous K1
key
JWKS URL Service Level Expectations
Singpass requires that any JWKS is published on an endpoint that
is served behind HTTPS on port
443
using a TLS server certificate issued by a standard publicly verifiable CA issuer (no private CAs), with complete cert chain presented by the serveris publicly accessible (no IP whitelisting, mTLS or other custom HTTP header requirements outside standard HTTP headers such as
Content-Type
,Accept
)is able to respond in a timely fashion with respect to the below configuration
Per try timeout
3s
Max attempts
3
Cache duration for retrieved JWKS
1h
Note
While the above is a technical requirement; the user experience of your users may be affected if we are unable to retrieve your JWKS in a timely fashion upon our cache expiry due to slower token exchanges with your backend. We recommend aiming for this response to be as fast as possible based on an in-memory cache; or simple static asset retrieval.
If Singpass fails to retrieve a valid JWKS from the provided URL after cache expiry, the relying party’s token exchange will fail with an OAuth2/OIDC invalid_client
error in these circumstances:
if client assertions are used, and we are unable to validate the relying party’s assertion using their signing key
if encryption of returned ID tokens is required, and we are unable to retrieve the relying party’s preferred encryption key
Last updated
Was this helpful?