How to encode and decode jwt token using python

Decoding jwt using public key in python

Dinesh Kumar K B
Geek Culture

--

source: https://dock2learn.com/tech/how-to-encode-and-decode-jwt-token-using-python/

Introduction:

JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is used as the payload of a JSON
Web Signature (JWS) structure or as the plaintext of a JSON Web Encryption (JWE) structure, enabling the claims to be digitally signed or integrity protected with a Message Authentication Code(MAC) and/or encrypted.

https://www.rfc-editor.org/rfc/rfc7519

In plain text, JWT, or JSON Web Token, is an open standard used to share information between two parties securely — a client and a server. In most cases, it’s an encoded JSON containing a set of claims and a signature

Python provides multiple libraries to encode and decode JSON web tokens. To name a few,

PyJWT:

For our discussion, we will be using PyJWT as the library.

Encode:

import jwt


def encode_user():
"""
encode user payload as a jwt
:param user:
:return:
"""
encoded_data = jwt.encode(payload={"name": "Dinesh"},
key='secret',
algorithm="HS256")

return encoded_data


if __name__ == "__main__":
print(encode_user())

Output:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiRGluZXNoIn0.7Fwj-RvoEP2-LfB5q05pdTvMl7pFpoQgwXYq3EOLens


Process finished with exit code 0

The above code is quite self-explanatory. We have a payload as a python dict i.e. the data to be encoded and a secret key used to encode. Also we have used the algorithm HS256 for signing the token.The algorithms supported by PyJWT is provided here.

Breaking down a JWT token:

Let’s try and understand the structure of a JWT token.A JWT token typically contains a user’s claims.These represent data about the user, which the API can use to grant permissions or trace the user providing the token.The different components of a JWT token is separated with a period(.). A JWT token consists of 3 parts.Each section is comprised of base64url-encoded JSON containing specific information for that token

  1. Header
  2. Payload
  3. Signature

jwt.io can also be used to decode a JWT token and breaks it into the above mentioned components.

Decode:

import jwt


def decode_user(token: str):
"""
:param token: jwt token
:return:
"""
decoded_data = jwt.decode(jwt=token,
key='secret',
algorithms=["HS256"])

print(decoded_data)

Output:

/Users/dkb/VirtualEnvs/py3.11-env/bin/python3.11 /Users/dkb/Code/practice/my_jwt.py

{'name': 'Dinesh'}

Process finished with exit code 0

Decoding JWT using public key:

A public key can be used to decode a JWT. Usually these public keys should be made available to tenant using the below URI format. Every open id server has to provide this endpoint. In our case, the public key is called as a JSON Web Key.

The JSON Web Key (JWK) is a JSON object that contains a well-known public key which can be be used to validate the signature of a signed JWT.

If the issuer of your JWT used an asymmetric key to sign the JWT, it will likely host a file called a JSON Web Key Set (JWKS). The JWKS is a JSON object that contains the property keys, which in turn holds an array of JWK objects.

 https://--YOUR DOMAIN----/.well-known/jwks.json


Sample Response:

{
keys: [
{
alg: 'RS256',
kty: 'RSA',
use: 'sig',
n: 'tTMpnrc4dYlD8MtmPnW3xZNbLxkaGCUwTqeKB4dfLg11dEpMyQEc4JRxUvRzp9tz00r6lkZ1ixcvIiuB_eMVckU8VyFSFWBSAxp5duBk6lRpYk-QjK3kEdPxYLxyW84gNzwMi-XW8zxJbsOa-cRM9sCb62Qz2yfWoQfimoFXsCnVHq496kizO7gZ972JefvTce1_n9dd_1p0K6c14qcCXtF6hbA_gQ0N7h3IyloBqiusKyTsV-ZrMZDldZkI-4v7s49TdcRZgEOvSapMz5YyoDvAWzuWGEiljkjkCOo0Mr5Sioi2x0dBm6nJ2WVYfZrwEF5J',
e: 'AQAB',
kid: 'NTY2MjBCNzQ1RTLPQzk3NzczRRTMQ0E4NzE2MjcwOUFCRkUwRTUxNA',
x5t: 'NTY2MjBCNzQ1RTJPLzk3NzczRUNPO0E4NzE2MjcwOUFCRkUwRTUxNA',
x5c: [Array]
}
]
}

Now let’s write a python code to decode a JWT token using python-jose.

import jwt
import httpx


def decode_access_token(authorisation_token):

# get public key from jwks uri
response = httpx.get(url="your open id wellknown url to fetch public key")

# gives the set of jwks keys.the keys has to be passed as it is to jwt.decode() for signature verification.
key = response.json()

# get the algorithm type from the request header
algorithm = jwt.get_unverified_header(authorisation_token).get('alg')

user_info = jwt.decode(token=authorisation_token,
key=key,
algorithms=algorithm)

return user_info

I have used python-jose here just to show that there is no significant difference between these libraries. The code really doesn’t look different from PyJWT. Does it?

Summary:

Please note that anyone can decode the information contained in a JWT without knowing the private keys. For this reason, you should never put secret information like passwords or cryptographic keys in a JWT.

python-jose is a wrapper on top of PyJWT.

Note: The reason I have mentioned both the libraries is, sometimes your build pipeline like gitlab/Jenkins complains(for no reason) of having different/incompatible versions of cryptography with PyJWT.However using python-jose on such scenarios would be a quick solution without changing the code. I personally faced this issue and wanted to share this here.

--

--