Nikesh Kedlaya
Nikesh Kedlaya

Reputation: 712

How to decode JWT token with JWK in Python

I am developing an application where all the API's are protected by OAuth. I have received the access token from the client, but could not decode and validate the token.

I have JWK in the below format

{
  "keys": [
    {
      "kty": "RSA",
      "x5t#S256": "Some value",
      "e": "Some Value",
      "x5t": "Some Value",
      "kid": "SIGNING_KEY",
      "x5c": [
        "Some Value"
      ],
      "key_ops": [
        "verify",
        "encrypt"
      ],
      "alg": "RS256",
      "n": "Some Value"
    }
  ]
}

How to decode the JWT token using above JWK in Python?

Upvotes: 10

Views: 26642

Answers (3)

Mehdi Zare
Mehdi Zare

Reputation: 1381

I did a little bit of clean up on @jason's work:

import jwt
from typing import Dict, Any


def decode_jwt_token(token: str, auth_domain: str, audience: str) -> Dict[str, Any]:
    jwks_url = f'https://{auth_domain}/.well-known/jwks.json'
    jwks_client = jwt.PyJWKClient(jwks_url)
    header = jwt.get_unverified_header(token)
    key = jwks_client.get_signing_key(header["kid"]).key
    decoded = jwt.decode(token, key, [header["alg"]], audience=audience)
    return decoded

Upvotes: 4

Jason
Jason

Reputation: 1094

I know that this is long ago answered, but this may be useful to somebody.

If you are working against an OAuth provider that supports OpenID, you can use something like the following which does the following:

  1. Decodes the token without validation to get the issuer
  2. Retrieves the JWKs from the OpenID configuration
  3. Retrieves the key ID and algorithm from the token header
  4. Decodes and validates the token
from os import environ
import json
import urllib.request
import jwt;

def get_jwks_url(issuer_url):
    well_known_url = issuer_url + "/.well-known/openid-configuration"
    with urllib.request.urlopen(well_known_url) as response:
        well_known = json.load(response)
    if not 'jwks_uri' in well_known:
        raise Exception('jwks_uri not found in OpenID configuration')
    return well_known['jwks_uri']

def decode_and_validate_token(token):
    unvalidated = jwt.decode(token, options={"verify_signature": False})
    jwks_url = get_jwks_url(unvalidated['iss'])
    jwks_client = jwt.PyJWKClient(jwks_url)
    header = jwt.get_unverified_header(token)
    key = jwks_client.get_signing_key(header["kid"]).key
    return jwt.decode(token, key, [header["alg"]])

token = "xxxyyyzzz"
decoded = decode_and_validate_token(token)
print(decoded)

Upvotes: 10

dejanualex
dejanualex

Reputation: 4358

Fast check of your jwt token https://jwt.io/

otherwise you can try this, but you should know the algorithm used to generate the token (e.g. : HS256) and the key used for signing the token) (e.g. :super_secretkey)


import jwt # pip install pyjwt[crypto] to install the package
jwt.decode(token, key='super_secretkey', algorithms=['HS256', ])

Update decode the JWT using JWK

import json
import jwt

#for JWKS that contain multiple JWK
public_keys = {}
for jwk in jwks['keys']:
    kid = jwk['kid']
    public_keys[kid] = jwt.algorithms.RSAAlgorithm.from_jwk(json.dumps(jwk))

kid = jwt.get_unverified_header(token)['kid']
key = public_keys[kid]

payload = jwt.decode(token, key=key, algorithms=['RS256'])

Upvotes: 25

Related Questions