Token Request with Private Key JWT fails

Intro

We are integrating CIS2 login into our app with the Integration Test environment.

The CIS2 flow successfully returns the authorisation code to the registered callback URL for the frontend. The frontend forwards the code to the backend for completing the authorisation flow.

As per the documentation on making a Token Request in the Authorization Code Flow page, the backend sends a POST request to the token_endpoint specified in the Discovery → INT → OpenID config, where we added the following parameters using the application/x-www-form-urlencoded format:

  • grant_type"authorization_code"
  • code → authorization code from frontend
  • redirect_uri
    • redirect URI set in [Developer HubEnvironment AccessIntegration TestCallback URL]
    • also set in redirect_uris as part of the integration env Connection Manager
  • client_id → as specified by the integration env Connection Manager
  • client_assertion_type"urn:ietf:params:oauth:client-assertion-type:jwt-bearer"
  • client_assertion → see below

We did not specify a client_secret, which isn’t part of the table but is in the example post request… is this needed? If so, where can I find the client_secret?

Client assertion

We built out a client_assertion JWT using the following header:

{
  "kid": "<key ID matches private key JWT in jwks_uri>",
  "alg": "RS256"
}

The body is as follows:

{
  "iss": "<client_id>",
  "sub": "<client_id>",
  "aud": "<token_endpoint exactly as specified in OpenID config>",
  "exp": 1750525580, // time + 5 min
  "jti":"<random UUID>"
}

The error

Despite the care taken, we encounter the following response:

{
  "error_description":"JWT is not valid",
  "error":"invalid_client"
}

Any ideas on what the error might be? Have we left an attribute out? Did we not take care of a subtle detail (such as the token_endpoint needing :443 before the path)?

Hi Faraz, can you DM me the JWKS endpoint and an exact JWT being sent so I can identify the issue. The audience must exactly match our guidance including the 443 port. Also the JWKS must contain a keys attribute with an array of values - it also has to be publicly readable

any updates @john.lister3?