ory / hydra

The most scalable and customizable OpenID Certified™ OpenID Connect and OAuth Provider on the market. Become an OpenID Connect and OAuth2 Provider over night. Broad support for related RFCs. Written in Go, cloud native, headless, API-first. Available as a service on Ory Network and for self-hosters.
https://www.ory.sh/?utm_source=github&utm_medium=banner&utm_campaign=hydra
Apache License 2.0
15.62k stars 1.5k forks source link

Wrong KID in headers of ID Token for a Refresh Token #3573

Open jvisker opened 1 year ago

jvisker commented 1 year ago

Preflight checklist

Describe the bug

When requesting a refresh token we are seeing a case where the headers of the included id_token state one KID value, but in reality it is signed by a newer KID. This behavior occurs with refresh tokens that existed before we added a new keyset for "hydra.openid.id-token". I have been trying to parse through the source code, but I think the crux of the issues is KID is saved in the session and when a new keyset is added it is unaware. If this was a bug that you fixed in a newer version that would be great to know as well. I acknowledge that this may be user error on our part, but I can't figure out how it could be.

Reproducing the bug

For us the steps to reproduce are:

  1. Go through an authcode flow and log in process that gives back an refresh token and id token
  2. Add a new keyset for “hydra.openid.id-token”
  3. Use the refresh token to get a new access token and id token
  4. Inspect the id token and validate that the KID and signature do not work together

Relevant log output

No response

Relevant configuration

No response

Version

1.11.8

On which operating system are you observing this issue?

Linux

In which environment are you deploying?

Docker

Additional Context

No response

aeneasr commented 1 year ago

Hi, please upgrade to 2.x as we have done some major reworking in the JWKs logic. Thanks!

tilgovi commented 2 months ago

I can confirm a similar experience with JWT access tokens. After performing a key rotation, refresh tokens still use the old kid but are signed by the new key.

tilgovi commented 2 months ago

I'm not sure if I'm following right, but a quick attempt to debug leads me to maybe these places:

When generating an access token with the JWT strategy, it looks like the headers from the existing JWT session get copied over.

terev commented 2 months ago

@tilgovi What version of Hydra are you using?

tilgovi commented 2 months ago

v2.2.0, the latest release

tilgovi commented 1 month ago

The (unreleased) change in ory/fosite#799 ensures that kid is set based on whatever key is used at the time signing is done, but it's still overwritten by the kid being passed as explicit extra headers. Removing KID from Session in Hydra fixes this issue. I don't know if that's a breaking change or not, but if it's possible to make a release of Fosite then I'll open a PR here to upgrade and remove the superfluous code in Hydra and we can discuss in the PR what it might take to merge that.