# Client Assertions

A client assertion is a JWT directly produced by a client application using a cryptographic key and presented as proof of the client's identity. (Refer to <https://datatracker.ietf.org/doc/html/rfc7521>)

Client Assertions provide a strong method of authenticating clients before returning an access\_token for them to access the data.

<figure><img src="https://1982108655-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fk67iNluSpweCPqhbIY5t%2Fuploads%2F8DDy98VX6BGQ5QmJg9S4%2Fimage.png?alt=media&#x26;token=805380bc-0e5d-4bba-aa47-360efd4a9689" alt=""><figcaption></figcaption></figure>

1. Client application invoke the Token API with a JWT client\_assertion.
2. AuthZ server will retrieve the client's trusted public key (JWK) from the client's onboarded JWKS URI. (As the JWKS endpoint only exposes public information, it does not need securing)
3. AuthZ server will verify the signature of the client\_assertion by extracting the matching public key from the client's JWKS with reference to the kid field in the client\_assertion JWT header.
4. AuthZ server returns the JWT access\_token.
5. Client application will retrieve AuthZ's trusted public key (JWK) from AuthZ's JWKS URI.
6. Client application will verify the signature of the access\_token by extracting the matching public key from AuthZ's JWKS with reference to the kid field in the access\_token JWT header.

{% hint style="info" %}
JSON Web Key (JWK) is a JSON object that represents a cryptographic public key that can be used to validate the signature of a signed JSON Web Token (JWT).

JSON Web Key Set (JWKS) is composed of 1 or more JSON Web Keys (JWK) in an array format.&#x20;
{% endhint %}

***

## **Generate Client Assertion**

An example JWT client assertion is shown below.

```
{
    "typ": "JWT",
    "alg": "ES256",
    "kid": "x0zDLIC9yNRIXu3gW8nTQDOMNe7sKMAjQnZj3AWTW2U"
}.
{
    "sub": "PROD2-MYINFO-SELF-TEST",
    "jti": "jNDZuyLw66gkTjmCNMawzrTJNlhS8wdjpU0DHTzo",
    "aud": "https://api.myinfo.gov.sg/com/v4/token",
    "iss": "PROD2-MYINFO-SELF-TEST",
    "iat": 1662365106,
    "exp": 1662365406,
    "cnf":{
        "jkt": "G_q8Qv9-xv_9xJo-esolTnvxVSobMER7O0LKGPBlTqY"
    }
}.
[signature]
```

The claims (Refer to <https://www.rfc-editor.org/rfc/rfc7519#section-4.1>) expected in the signed assertion are:

| PARAMETER | DESCRIPTION                                                                                                                                    |
| --------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| sub       | Subject - client\_id issued by Myinfo upon onboarding                                                                                          |
| jti       | JWT ID - random unique identifier                                                                                                              |
| aud       | Audience - URL that client application is calling                                                                                              |
| iss       | Issuer - client\_id issued by Myinfo upon onboarding                                                                                           |
| iat       | Issued At - current timestamp                                                                                                                  |
| cnf.jkt   | JWK Thumbprint - base64url encoding of the JWK SHA-256 Thumbprint of the client's ephemeral public signing key used to sign the DPoP Proof JWT |

**Sample Code:**

```
// jktThumbprint: base64url encoding of the JWK SHA-256 Thumbprint of the client's ephemeral public signing key used to sign the DPoP Proof JWT
     
    async function generateClientAssertion (url, clientId, privateSigningKey, jktThumbprint) => {
      let now = Math.floor((Date.now() / 1000));
     
      let payload = {
        'sub': clientId,
        'jti': generateRandomString(40),
        'aud': url,
        'iss': clientId,
        'iat': now,
        'exp': now + 300,
        'cnf' : {
          'jkt': jktThumbprint
        }
      };
      let jwsKey = await jose.JWK.asKey(privateSigningKey, 'pem');
     
      let jwtToken = await jose.JWS.createSign({ 'format': 'compact', 'fields': { 'typ': 'JWT' } }, jwsKey).update(JSON.stringify(payload)).final();
      return jwtToken;
    };
```

The client\_assertion is produced by generating the JSON payload and signing it with a private key. The signing and headers are produced by a JWT security library which uses a private key in JWK format.&#x20;
