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...