Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JWT decode requires audience #870

Closed
ddtxra opened this issue Mar 17, 2023 · 3 comments
Closed

JWT decode requires audience #870

ddtxra opened this issue Mar 17, 2023 · 3 comments
Labels
stale Issues without activity for more than 60 days

Comments

@ddtxra
Copy link

ddtxra commented Mar 17, 2023

Hello,
I tried to use the documentation found in here: https://pyjwt.readthedocs.io/en/latest/usage.html#retrieve-rsa-signing-keys-from-a-jwks-endpoint related to the validation of a JWT token using JWKS but it was not working for me using Keycloak issuer.

Then I searched for more documentation on Google and found out this great blog post: https://renzolucioni.com/verifying-jwts-with-jwks-and-pyjwt/

At the end I wrote down this code which worked for me (and could be useful for someone else, so I paste it here)

    token_response = oauth.keycloak.authorize_access_token()
    id_token = oauth.keycloak.parse_id_token(token_response)

    # Reads the keys from JWK and creates a dictionary with the RSAPublic keys
    jwk_uris = requests.get(f'{issuer}/.well-known/openid-configuration').json()["jwks_uri"]
    jwks = requests.get(jwk_uris).json()

    public_keys = {}
    for jwk in jwks['keys']:
        kid = jwk['kid']
        public_keys[kid] = jwt.algorithms.RSAAlgorithm.from_jwk(json.dumps(jwk))

    if id_token:
        logging.debug('logged in ' + id_token['email'])
        session['user'] = id_token
        token = token_response['access_token']
        # get the identifier of the key used from the header token
        kid = jwt.get_unverified_header(token)['kid']
        # gets the key associated
        key = public_keys[kid]
        try:
            session['resource_access'] = jwt.decode(token, key=key, audience="app_****", algorithms=["RS256"])['resource_access']
        except jwt.exceptions.MissingRequiredClaimError as exc:
            session['resource_access'] = {}

But at the end I still have problem with this code. Why do I need to specify an audience?
Some of my users don't have the required resource_access for the specified audience, so the token does not contain the "aud" field, which is ok. But when those users try to login, the decode function crashes with MissingRequiredClaimError.
Is there a way to specify all audiences or ignore this field? It seems mandatory to set in the decode function and also the token must contain the "aud" field...

@Viicos
Copy link
Contributor

Viicos commented Apr 1, 2023

I tried to use the documentation found in here: https://pyjwt.readthedocs.io/en/latest/usage.html#retrieve-rsa-signing-keys-from-a-jwks-endpoint related to the validation of a JWT token using JWKS but it was not working for me using Keycloak issuer.

That may be because of #863, your JWK endpoint might be returning unsupported keys and PyJWT currently fails to ignore them.

But at the end I still have problem with this code. Why do I need to specify an audience?
Some of my users don't have the required resource_access for the specified audience, so the token does not contain the "aud" field, which is ok. But when those users try to login, the decode function crashes with MissingRequiredClaimError.
Is there a way to specify all audiences or ignore this field? It seems mandatory to set in the decode function and also the token must contain the "aud" field...

By default, even if you don't pass any value to the audience parameter of decode, PyJWT will validate the aud claim, if present in the token. Validation will succeed if there's no aud claim in the token.

But as you are explicitly setting the audience to app_****, PyJWT will raise an error even if no aud claim is available in the token.

To disable the aud validation, use:

jwt.decode(token, key=key, algorithms=["RS256"], options={"verify_aud": False"})

@github-actions
Copy link

github-actions bot commented Jun 1, 2023

This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days

@github-actions github-actions bot added the stale Issues without activity for more than 60 days label Jun 1, 2023
@Viicos
Copy link
Contributor

Viicos commented Jun 1, 2023

as #863 is now fixed, this can be closed.

@jpadilla jpadilla closed this as completed Jun 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stale Issues without activity for more than 60 days
Projects
None yet
Development

No branches or pull requests

3 participants