How to Handle JWTs in Python

Learn how to create, parse and verify your JWTs in Python using PyJWT.
Read more

Brought to you by @jesstemporal

What’s up pythonistas! How did you like this post? Please share any comments or feedback with us on this thread :speech_balloon: :thought_balloon:

Previous message deleted due to SPAM reasons.

1 Like

I am able to generate a jwt using python, but when I go to jwt.io, enter my generated token, add my secret (to verify signature), and then enable ‘Secret base64 encoded’ (with my secret value), I see the signature changes. Disable, it goes back to my generated token. How can I generate a token that has the signature base64 encoded? i’ve tried all kinds of things (I did split out the header/payload since they don’t change, and tried to ‘base64 encoded’, but nothing seems to work. I’ve googled around, I see a few other folks have the same question, one guy actually seemed to have found the answer using java, but I can’t seem to replicate his answer in python.

This article has a serious security concern. If the advice is followed, it can leave the server open to attack.

The article is a good overview of JWT and how to generate and inspect JWTs. However, someone reading might naievely use the examples without context as a basis for actual production code.

In the section " Find out the algorithm used in a JWT", it has the following code:

# saving the header claims into a variable
header_data = jwt.get_unverified_header(token)

# using that variable in the decode method
jwt.decode(
    token,
    key='my_super_secret',
    algorithms=[header_data['alg'], ]
)

The vulnerability here is that the JWT token could contain the alg “none”. This would bypass signature validation and allow an attacker to forge any token without having to know the secret.

RFC 8725 has best practices for JWT tokens:

2.1 “The algorithm can be changed to “none” by an attacker, and some libraries would trust this value and “validate” the JWT without checking any signature.”

3.1 “each key MUST be used with exactly one algorithm, and this MUST be checked when the cryptographic operation is performed.”

I recommend changing the examples to remove any usage of algorithms=[header_data['alg'], ]. Someone blindly copy/pasting would not understand the implications of this.

Hi @six8,

Thanks for sharing your findings with us. Normally when we write articles that explain how to secure an application we pass the algorithm from an app settings (or environment variable), which should match the same algorithm the authorization server uses to sign the JWT, here is an example: Build and Secure a FastAPI Server with Auth0

I’ll review the wording and add a note or partially rewrite this article to prevent any reader to get into confusion here, and thinking the code provided in the article is production ready.

Thanks a gain, I’ll post here again once the article is revised.

1 Like