# Generation Of Client Assertion

{% hint style="info" %}
If you are using a [certified OIDC Relying Party library](https://openid.net/developers/certified-openid-connect-implementations/), the generation of client assertion will be handled by the library, as long as you specify that the `private_key_jwt` method is used for authentication.
{% endhint %}

## Overview

When your backend calls our APIs, you will need to generate a client assertion to authenticate yourself. The generation of this client assertion should be done using the `private_key_jwt` mechanism specified in the [OIDC specifications](https://openid.net/specs/openid-connect-core-1_0-final.html#ClientAuthentication). This mechanism involves you building a client assertion by signing a JWT using one of your signing keys defined in your [JWKS](https://docs.developer.singpass.gov.sg/docs/technical-specifications/technical-concepts/json-web-key-sets-jwks).

Client assertions need to be sent in the [Pushed Authorization Request](https://docs.developer.singpass.gov.sg/docs/integration-guide/1.-authorization-request#id-1.-sending-the-pushed-authorization-request) and the [Token Request](https://docs.developer.singpass.gov.sg/docs/technical-specifications/integration-guide/3.-token-exchange).

## Generation of JWT

To reduce complexity, we recommend that you use a JWT library to perform the JWT encoding and signing on your behalf, instead of implementing this on your own. You may refer to [this list](https://www.jwt.io/libraries?support=sign\&algorithm=es256) to look for a suitable library for your programming language. To learn more about JWTs and their structure, you may read [this article](https://www.jwt.io/introduction).

The JWT must have the structure outlined below.

### JWT Header

The JWT header should contain the following parameters:

<table><thead><tr><th width="122.17578125">Parameter</th><th>Description</th><th>Data Type</th></tr></thead><tbody><tr><td><code>alg</code></td><td>The signature algorithm that you are using to sign this JWT</td><td><p>One of the following strings:</p><ul><li><code>ES256</code></li><li><code>ES384</code></li><li><code>ES512</code></li></ul></td></tr><tr><td><code>typ</code></td><td>The type of this JWT</td><td>Must be the string <code>JWT</code></td></tr><tr><td><code>kid</code></td><td>The <code>kid</code> of the signing key that you are using to sign this JWT header.<br><br>If this is not provided, we will test against all of the signing keys in your JWKS when attempting to verify the signature.</td><td>String, optional</td></tr></tbody></table>

<details>

<summary>Sample JWT header in JSON form</summary>

```json
{
  "typ": "JWT",
  "alg": "ES256",
  "kid": "my_key_id_01"
}
```

</details>

### JWT Payload

The JWT payload should contain the following claims:

<table><thead><tr><th width="88.7265625">Claim</th><th width="440.61328125">Description</th><th>Data type</th></tr></thead><tbody><tr><td><code>sub</code></td><td>The client ID of your registered client, provided by Singpass during app onboarding.</td><td>A 32-character case-sensitive alphanumeric string.</td></tr><tr><td><code>aud</code></td><td>This should be the issuer identifier of our authorization server. You can obtain this value from the <code>issuer</code> field in the OpenID configuration of our authorization server.</td><td>String</td></tr><tr><td><code>iss</code></td><td>The client ID of your registered client, provided by Singpass during app onboarding.</td><td>A 32-character case-sensitive alphanumeric string.</td></tr><tr><td><code>iat</code></td><td>The unix timestamp, in seconds, at which you generated this JWT.</td><td>Number</td></tr><tr><td><code>exp</code></td><td>The unix timestamp, in seconds, on or after which this JWT <strong>must not</strong> be accepted by us for processing.<br><br>Note also that this must be less than or equal to 2 minutes after <code>iat</code>.</td><td>Number</td></tr><tr><td><code>jti</code></td><td>A unique identifier for this token. This identifier must only be used once. You should generate a new <code>jti</code> value for every request</td><td>String</td></tr></tbody></table>

<details>

<summary>Sample JWT Payload in JSON form</summary>

```json
{
  "sub": "T5sM5a53Yaw3URyDEv2y9129CbElCN2F",
  "aud": "https://id.singpass.gov.sg/fapi",
  "iss": "T5sM5a53Yaw3URyDEv2y9129CbElCN2F",
  "iat": "1756785377",
  "exp": "1756785493",
  "jti": "59e05e3c-9418-4e63-8119-a05157219b74"
}
```

</details>

### Overall JWT (Signed and Encoded)

The JWT should be signed using your private key to form a JSON Web Signature (JWS) in compact serialisation format. This is a format where the three parts of the JWS (the header, the payload, and the signature), are base64url encoded and concatenated together, using a dot (`.`) as the separator.

You must publish the public key corresponding to the private key you used to sign this JWT in your [JWKS](https://docs.developer.singpass.gov.sg/docs/technical-specifications/technical-concepts/json-web-key-sets-jwks).

<details>

<summary>Sample Signed JWT (in Compact Serialisation Format)</summary>

{% code overflow="wrap" %}

```
eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6Im15X2tleV9pZF8wMSJ9.eyJzdWIiOiJUNXNNNWE1M1lhdzNVUnlERXYyeTkxMjlDYkVsQ04yRiIsImF1ZCI6Imh0dHBzOi8vaWQuc2luZ3Bhc3MuZ292LnNnL2ZhcGkiLCJpc3MiOiJUNXNNNWE1M1lhdzNVUnlERXYyeTkxMjlDYkVsQ04yRiIsImlhdCI6IjE3NTY3ODUzNzciLCJleHAiOiIxNzU2Nzg1NDkzIiwiY29kZSI6IlhjeXpsU2VYMWhJeUpGbHN0eHNTRl9VZVhDNUR0aVlrRmdKOFZWeDUybWcifQ.fQMHTVNeCsa_mK6pmfjfi0rxERxDtu6eiMFkkpFdQrirc3u9LxP1_-E_7yIalIhmot1NdBQxbA9s_VztlQUhTQ
```

{% endcode %}

</details>
