lepture / authlib

The ultimate Python library in building OAuth, OpenID Connect clients and servers. JWS,JWE,JWK,JWA,JWT included.
https://authlib.org/
BSD 3-Clause "New" or "Revised" License
4.54k stars 452 forks source link

Allow reading an unvalidated JWT's header #307

Open thatguysimon opened 3 years ago

thatguysimon commented 3 years ago

Is your feature request related to a problem? Please describe.

When validating a JWT using a JWKS, it is common to read the kid claim from the JWT's header in order to pull the correct JWK from the set. For example: https://auth0.com/docs/quickstart/backend/python/01-authorization#create-the-jwt-validation-decorator

Currently in order to read the contents of the JWT we have to initialize and run a JWTBearerTokenValidator instance, but we can't initialize it without the key that we want to get from the JWKS. So we're sort of stuck in a deadlock here.

Describe the solution you'd like

A helper function, similar to PyJWT's get_unverified_header, which allows reading an unvalidated JWT's header.

Describe alternatives you've considered

Using PyJWT itself, but it's a shame to add another dependency just for this.

This library is awesome by the way, thanks!!

lepture commented 3 years ago

@thatguysimon our key accepts a function:

def load_key(header, payload):
    kid = header['kid']
    return keys[kid]

jwt.decode(s, key=load_key, ...)

jwt.decode also support jwks as key:

jwks = {'keys': [...]}

jwt.decode(s, key=jwks, ...)

However, I would like to add such a method in the future.

thatguysimon commented 3 years ago

Thanks @lepture, this was very helpful! Is it documented anywhere? I couldn't find anything about this in the docs.

relsunkaev commented 2 years ago

In my use case, getting the key requires making a call with the kid using async API bindings. I don't want to have to start up another loop in another thread so being able to get an unverified header would be very useful.

evelyn9191 commented 9 months ago

I'm in the same deadlock situation - I need to read the unvalidated header at the moment when the key for decoding is not yet available. It would be great if authlib would have this feature. For now, I had to solve it by using a different library, unfortunately.

parikls commented 2 months ago

+1 for this

lepture commented 2 months ago

@evelyn9191 @thatguysimon It is very easy to get the unverified header with:

from authlib.jose.errors import DecodeError
from authlib.jose.util import extract_header

header = extract_header(token.split('.')[0], DecodeError)