I'm using Okta for identity management. As the client in authorization flow, I send an authorize request to Okta. This works successfully, and I get a JWT payload. I want to verify the JWT signature, so I make another call to Okta in order to fetch the keys. However, the key ids (kids) do not match and verification fails.
Initial authorize request:
https://{{site}}.okta.com/oauth2/v1/authorize
?scope=openid
&response_type=id_token
&client_id={{client_id}}
&redirect_uri={{redirect_url}}
&nonce=4euiv0v52at3la15e7qlu1mt43
&state=7c92bqulrmdk2jk0ro9rd3mf5j
Response is a 403, redirecting me to:
{{redirect_url}}/id_token={{id_token}}
The header of the id_token is decoded into:
{
"alg": "RS256",
"kid": "2YKtkekCjCRWN0YqGsjUrNwIQaxGg5ahfHW0_fK8t64"
}
So far so good. I know that the authorization has succeeded. Time to validate the JWT.
However, when this is followed up with:
https://{{site}}.okta.com/oauth2/v1/keys
Or
https://{{site}}.okta.com/oauth2/v1/keys?clientId={{client_id}}
(they both return the same response), I get back this:
{
"keys": [
{
"alg": "RS256",
"e": "AQAB",
"n": "gv1rI9A7mrOoViJZTzUfiZl7YdEzLEofvRoVbXCgeW7aOmoKcAkWGHvqNRGoFgi8auV5b_TSgTXKq_TV1fz643hpAtba3V0Uw2lXchTbqXpmVRYXI1t4FIwRMXLe4Q-kcvp9la21e3D1lszjdPbFNX5GLAhrCW0Thu2HYbTLg6TbDTMaiQCMo15hek0JgZqRGzCkt9kINnwPVLXV_bkSh_fHWo_6G1L0MKYYQcgE6zvPlULLek98-yZ6Nlg6nJUY9nHn0qjhzqqq-bz_Vin8qi3Bt7SjUKwk7HbaugM84AEgDxYE5JgsaALIl5SgIc3GgFEc69qKWymoD-w1a8f1HQ",
"kid": "SOxFkBSLWefjlZoDI49Hk0nqlYtC28cjhTlVAYEzAxs",
"kty": "RSA",
"use": "sig"
}
]
}
Where the kid does not match what I received in the original response.
Where is my mistake?
The problem was that this account was setup with pinned, not rotating keys. oauth2/v1/keys requires the client id to be passed in as a parameter if you are setup with pinned keys; the correct parameter name is "client_id", not "clientId." This results in the expected output.