Using token_endpoint_auth_method as private_key_jwt with multiple jwks

Hi,

I was able to execute a client credential flow using a token_endpoint_auth_method of private_key_jwt when I registered just a single key in the jwks property of the client. That is, I was able to sign a JWT and send it to the /token endpoint via a client_assertion and get back a token.

However, if I register a set of more than one key in the jwks for the client, using unique kids, I only get an error from the /token endpoint:

{
  "error": "invalid_client",
  "error_description": "The client_assertion JWT kid is invalid."
}

I am in fact including a kid claim in the signed client_assertion JWT that matches the corresponding kid in the client’s jwks, so I don’t understand why I’m getting this error.

Are there any special rules around how to assign kids to the JWKs? In this particular example I am simply using the string "1" for the kid.

Has anyone else successfully used clients with multiple keys in jwks?

Thanks,

Oops, amateur hour over here, heh; I was putting the kid in the JWT body instead of its header. Once I put the kid in the header all worked as expected.

1 Like

It’s not amateur hour over here. All “kidding” aside, I have the kid in the header and its throwing this error. The kid was generated by jsrsasign API jsrsasign JavaScript API Reference - KEYUTIL which claims conformance to RFC 5280 - Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile. The JWT looks like this:

Header:
{
“alg”: “RS384”,
“kid”: “15202328c44555056638e47a1d6218c0fae3bc88”,
“typ”: “JWT”
}
Payload: (iss, subj, and aud are omitted by the forum)
{
“exp”: 1618650352,
“iss”: ,
“sub”: ,
“aud”: ,
“jti”: “52e39635-cf97-4c63-a2ac-3d7a1068ca72”
}

What does Okta expect for the kid? BTW, I also tried a uuid with same result…

A little more investigation reveals that when the client was registered, the kid was not sent in to Okta at all causing Okta to default the kid value to null. This was the response from Okta when the app was registered via DCRP:

{

"client_id": "<clientid>",

"client_id_issued_at": 1618648612,

"client_name": "Test Client",

"client_uri": null,

"logo_uri": null,

"redirect_uris": [],

"response_types": [

    "token"

],

"grant_types": [

    "client_credentials"

],

"jwks": {

    "keys": [

        {

            "kty": "RSA",

            "kid": null,

            "use": null,

            "e": "AQAB",

            "n": "cryptobabble"

        }

    ]

},

"token_endpoint_auth_method": "private_key_jwt",

"application_type": "service"

}

the “kid” value you set for each key should be sent as part of each JWKS key, which you can see in this example (borrowed from our API docs):

curl -X POST \
-H 'Accept: application/json' \
-H "Authorization: SSWS ${api_token}" \
-H 'Content-Type: application/json' \
-d ' {
	"client_name": "Example Service Client",
	"response_types": [
		"token"
	],
	"grant_types": [
		"client_credentials"
	],
	"token_endpoint_auth_method": "private_key_jwt",
	"application_type": "service",
	"jwks": {
		"keys": [
			{
				"kty": "RSA",
				"e":"AQAB",
				"kid": "key1",
				"n":"AJncrKuine49_CEVR4GPn.....zOrouIUCSMlRL0HU="
			}
		]
	}
}' 
"https://${yourOktaDomain}/oauth2/v1/clients"
1 Like

I ran into a similar thing, finding this comment made my day, thanks!

1 Like