Setup Client Assertion
A Client Assertion is a JWT directly produced by a client application using a cryptographic key and is presented as proof of the client's identity. Client Assertions provide a strong method of authenticating clients before returning an access_token for them to access the data.
Relying Party (RP) is required to present an assertion JWT in the request body when calling the token endpoint. Singpass will then verify this JWT against a JWK provided by the RP in the Application configuration.
RP is required to generate an assertion JWT that has the following header and claims, and is signed with the JWK indicated in the Application configuration.
Step 1: Define Client Assertion
The JWK Header should have the following attributes:
Example of JWT Header
{
"typ": "JWT",
"alg": "ES256",
"kid": "sig-2024"
}
The JWK Claims should have the following attributes:
sub
This should be client_id
of the registered client provided in the Application configuration for each Application
aud
The recipient that the JWT is intended for. This must match the issuer
field in the response endpoint
Example: https://id.singpass.gov.sg
iss
This should be client_id
of the registered client provided in the Application configuration for each Application
iat
The time at which the JWT was issued. Ref
exp
The expiration time on or after which the JWT MUST NOT be accepted by NDI for processing. Additionally, NDI will not accept tokens with an exp
longer than 2 minutes since iat.
Ref
code
(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.
Example of JWT Claims
{
"sub": "alh5DS2Gfndv9i0jXYViqGIhiQdP4+4BrUvBhDXBYKk=",
"aud": "https://stg-id.singpass.gov.sg",
"iss": "alh5DS2Gfndv9i0jXYViqGIhiQdP4+4BrUvBhDXBYKk=",
"iat": 1609907375,
"exp": 1609907975
}
The JWK Signature
The JWT assertion signature is a crucial component. RP to ensure the JWT assertion is signed with the JWK private key to the public keys provided by the RP in the Application configuration.
Example of JWT Client Assertion
{
"typ": "JWT",
"alg": "ES256",
"kid": "testing123"
},
{
"sub": "alh5DS2Gfndv9i0jXYViqGIhiQdP4+4BrUvBhDXBYKk=",
"aud": "https://stg-id.singpass.gov.sg",
"iss": "alh5DS2Gfndv9i0jXYViqGIhiQdP4+4BrUvBhDXBYKk=",
"iat": 1609907375,
"exp": 1609907975
},
[Signature]
Step 2: Add the Client Assertion function to the Application
Here is a sample code that can be referenced as a function to generate client assertion.
Create a new function file in your application called generateClientAssertion.js.
Install the JOSE (JSON Object Signing and Encryption) package which will be used to generate and sign the client assertion. Open the terminal, use
npm install jose
to install the package.
npm install jose
Copy the following code into the generateClientAssertion.js file. Update the signature keys, JWT claims value, and the key ID as explained above.
//generateClientAssertion.js
const alg = "ES256";
//Signature Private Keys JWT
const jwk =
{
kty: "EC",
d: "0GlHbGc8vSnyiB-Lf4_im_WFwrxM0MJjkk96o1-K3JQ",
crv: "P-256",
x: "wg11s6ZpBc0my5gT-mYatTZRDhgStyd_0qARVBwAWa4",
y: "hlVoYWwlCuTMnm79Ppmf3RslIwDRhqdCCnm01PkhA2s",
};
const privateKey = await jose.importJWK(jwk, alg);
const nowTime = moment().unix();
const futureTime = moment().add(2, "minutes").unix();
const jwt = await new jose.SignJWT({
sub: "tLRDBkf1CNy5Rsi34mEKuOD5EpQAwjIq", //Update Client ID
iss: "tLRDBkf1CNy5Rsi34mEKuOD5EpQAwjIq", //Update Client ID
aud: "https://stg-id.singpass.gov.sg",
iat: nowTime,
exp: futureTime,
})
.setProtectedHeader({
alg: "ES256",
kid: "sig-2024", //Update KeyID from the Signature JWT
typ: "JWT",
})
.sign(privateKey);
console.log(jwt);
Run the function. Below is the sample client assertion output of the console.log.
eyJraWQiOiJycF9rZXlfMDEiLCJ0eXAiOiJKV1QiLCJhbGciOiJFUzM4NCJ9.eyJzdWIiOiIwamVYZ2dMd3JFelNDcGRmdHpzNmlHbXdZbWNMS3F4TiIsImF1ZCI6Imh0dHBzOi8vc3RnLWlkLnNpbmdwYXNzLmdvdi5zZyIsImNvZGUiOiJuMGVzYzNOUnplN0xUQ3U3aVl6UzZhNWFjYzNmMG9ncDQiLCJpc3MiOiJodHRwOi8vZXhhbXBsZS5jb20iLCJleHAiOjE3MTQ5ODMzNDcsImlhdCI6MTcxNDk4MzIyN30.AAAAAAAAAAAAAAAAAAAAAO_3oh85dPCvrYpZhH8DyQW97csQhrgqwzmXTb6XU2S0AAAAAAAAAAAAAAAAAAAAAHkNRM-g9kT1bwPMYQsJ6lU9Drn-_Zcjht5pbR_FF0f_
If you passed the verification, your client assertion is ready to be used for the later steps.
Next steps
Proceed to call the Token Endpoint to receive the ID Token.
Was this helpful?