ID Token Structure
An ID Token is a signed and encrypted JWT (JWE) issued by Corppass in the OpenID Connect Authorization Code Flow. It contains identity-related claims about the authenticated user and their associated entity, and is returned in the token response after successful authentication.
Parsing the ID token
Overview
The ID token is a JSON Web Encryption object (JWE), and the inner encrypted payload is a signed JWT (JWS).
The JWE is encrypted using the RP's public encryption key as configured in their JWKS object / JWKS endpoint, while the JWS is signed using Corppass private signing key.
High Level Steps
To process the ID token, clients must:
Use their private encryption key to decrypt the JWE.
Extract and validate the inner signed JWT (JWS).
Validate the signature using Corppass’s public signing key from the JWKS endpoint.
Validate the following claims:
iss
,aud
,exp
,iat
, andnonce
.
Structure
JWE
A JWE consists of five dot-separated Base64URL-encoded parts:
<protected header>.<encrypted key>.<initialisation vector>.<ciphertext>.<authentication tag>
Read the Key Concepts - JWS and JWE page to find out more about JWEs and how to handle them.
JWE Header
Example of a protected header:
{
"alg": "ES256",
"enc": "A256CGM",
"typ": "JWT",
"kid": "example-key-id"
}
Fields present in the JWE header:
alg
Key management algorithm — asymmetric ECDH-ES with AES key wrapping
enc
Content encryption algorithm — AES GCM
typ
Token type (always JWT
)
kid
Key ID — matches the encryption public key in the client's JWKS
Clients must use the kid field in the JWE header to identify the key Corppass used for encryption. Refer to RFC 7515 Section 4 for more information about the JWE structure.
Signed JWT
After decrypting the ID token (JWE), the payload retrieved will be a signed JWT. RPs must validate the signature.
Read the Key Concepts > JWS and JWE page to find out more about JWSs and how to handle them.
JWT Header
Example of the JWT header:
{
"alg": "ES256",
"typ": "JWT",
"kid": "example-key-id"
}
Fields present in the JWT header:
alg
Signing algorithm used by Corppass (e.g., ES256)
typ
JWT token type
kid
Key ID — matches a public key in Corppass’s JWKS for signature validation
Clients must use the kid
(Key ID) field in the JWS header to identify which public key from Corppass’s JWKS was used to sign the token. Refer to RFC 7515 – JSON Web Signature (JWS) for more information on the JWS structure.
JWT Claims
The decrypted JWT will have the following claims:
sub
String
Represents the subject principal of this JWT, which in this case is the entity that is being accessed on behalf of. It will be the entity's UEN (if it is of UEN type) or the Corppass Entity ID (if not UEN type).
Y
act
Object
Refers to the actor - the underlying user that is acting on behalf of the subject indicated by the sub
claim above.
See act for more details.
Y
sub_account
Object
Contains more information related to the subject principal of this token. Should always have account type "entity"
See sub_account - Entity Account for more details.
Y
aud
String
The client ID of your registered client as provided during client onboarding.
Y
iss
String
The issuer identifier of the Corppass authorization server.
Y
iat
Number
The unix timestamp, in seconds, at which the JWT is issued.
Y
exp
Number
The unix timestamp, in seconds, on or after which this JWT must not be accepted for processing.
Y
nonce
String
Refers to the same nonce that clients provided in the initial authorization request.
Y
amr
String Array
Authentication methods references used during Singpass Login. See amr for list of possible values.
Y
sub_account
The sub_account
claim may appear in two places -
As a top-level claim in the ID token, where it represents the identity of the Entity that is being represented. This claim will always be provided.
As a nested claim within the
act
claim, where it represents the identity of the Person that is acting on behalf of the entity. This claim will only be provided ifsub_account
scope is presented.
Account Types
The sub_account
claim is an object that will always contain an account_type
property, which reflects the type of account the subject principal holds.
{
"sub": "...",
"sub_account": {
"account_type": "entity", // attribute is always present
...,
...
},
"act": {
"sub_account": {
"account_type": "SC/PR"
...,
...
}
}
}
Entity Account
When this claim exists as a top-level claim in the ID token (ie. not nested inside act
claim), the account_type
value will always be entity
.
Depending on the type of entity, the other values returned in the object will differ as described below.
List of claims for sub_account describing an entity account
account_type
String
Will always be entity
in this case.
Y
entity_name
String
The name of the registered entity.
Y
entity_type
String
The entity type.
List of possible values are UEN
, NON-UEN
, GSTN
Y
entity_status
String
The entity status.
List of possible values are Registered
, Deregistered
, Withdrawn
.
Only provided if the represented entity is of type UEN
.
N
non_uen_country
String
The country of which the entity was registered in.
Only provided if the represented entity is a foreign company (NON-UEN
entity type).
N
non_uen_reg_no
String
The entity registration number in the foreign jurisdiction.
Only provided if the represented entity is a foreign company (NON-UEN
entity type).
N
User Account
This claim (act.sub_account
) will only be provided if the sub_account
scope is requested in the access token.
When this claim exists as a nested claim in the ID token (ie. nested under act
claim), it represents the underlying user that is acting on behalf of the entity.
In this case, the account_type
value can be one of the following types, depending on the user's residency status or type of pass that they are holding.
User Account Types
Singaporeans/PRs
SC/PR
FIN holder
FIN
Singpass Foreign Account
SFA
Depending on the user's account type, the other values returned in the object will differ as described below.
List of claims for sub_account describing a user account
uinfin
String
The acting user's NRIC or FIN number.
Only provided if the user account type is SC/PR
or FIN
.
N
name
String
The acting user's full name.
Y
String
The acting user's email address as registered on Corppass.
Only provided if the business_profile.email
scope is present in the access token.
N
email_verified
Boolean
Indicates whether the acting user's email has been verified by the user.
Only provided if the business_profile.email
scope is present in the access token.
N
foreign_id
String
The acting user's foreign ID number (e.g., passport or local ID).
Only provided if the user account type is SFA
N
foreign_id_coi
String
The country of issuance of the user's foreign ID. It is a 2-letter country code.
Only provided if the user account type is SFA
N
act
The act
claim is an object which in itself contains claims that identify the actor.
In Corppass case, the act
always refer to the acting user.
sub
String
The principal that represents the actor. It is a globally unique identifier of the user.
Y
sub_account
Object
Contains more information related to actor. Will never have account type value "entity"
Only provided if the sub_account
scope is requested by the RP in the initial authentication request.
See sub_account - User Account for more details.
N
amr
Note that the list below is non-exhaustive, and Singpass reserves the right to introduce new values without prior notice.
Some possible values are:
pwd
Password
otp-sms
SMS OTP
face
Face verification
face-alt
Alternative form of face verification.
swk
Software-secured key (i.e. QR/shortcut login via Singpass app)
hwk
Hardware-secured key (i.e. QR/shortcut login via Singpass app)
ID Token Samples
Verification Steps
Standard Claims Verification
For clients using a certified OIDC Relying Party library, these checks will be automatically performed by the library, though clients must still pass the nonce to the library for it to perform the nonce check.
In order to ensure that the ID token is valid, clients must perform the following checks:
Verify that the
iss
claim matches the issuer identifier of our authorization server, which you can obtain from theissuer
field in the OpenID configuration of our authorization server.Verify that the
aud
claim matches your client ID.Ensure that the current time is before the timestamp in the
exp
claim.Ensure that the
nonce
claim is the same as the nonce that you had sent in the authorization request.
at_hash Claim Verification
We also strongly encourage clients to use at_hash
claim to validate the Access Token's integrity, ensuring it has not been tampered with.
For more details on at_hash
claim, refer to Section 2 of the OIDC Core Specification.
Last updated