Token validation with python

Hello everyone,

Looking for some guidance on (access) token validation with python.

I started out using python-jose but that has lead me down a bit of a rabbit hole: jwks.json carries the x.509 certificate, but python-jose requires the public key. Trying to extract the public key has been a bit of an adventure and I started to think, there has to be a better way.

I have started looking at authlib instead, but if anyone has pointers or example code they can share, that would be appreciated. My google-fu hasnā€™t been much help yet. Iā€™d like to think it is as easy as verify(access_token, jwks_json).

Thanks,
Mark

Iā€™ve managed some minor success using pyjwt, though there must still be an easier way to do this. The certificate in /.well-known/jwks.json is x.509. pyjwt requires the public key, so you need to extract that from the cert. This can probably be done without ā€œreconstitutingā€ the cert as I have done, but it works. cert is the x.509 certificate string from jwks.json:

from cryptography.x509 import load_pem_x509_certificate
from cryptography.hazmat.backends import default_backend

def extract_public_key(cert):
    cert_string = textwrap.wrap(cert, width=64)
    cert = '-----BEGIN CERTIFICATE-----\n'
    for line in cert_string:
        cert += line + '\n'
    cert += '-----END CERTIFICATE-----\n'
    cert_obj = load_pem_x509_certificate(cert.encode(), default_backend())
    return cert_obj.public_key()

Then I validate the audience. env holds config parameters like the client ID, audience:

import jwt

def validate_token(token, jwks, env):
    public_key = extract_public_key()jwks['x5c'][0]
    return jwt.decode(token['access_token'], public_key, audience=env['audience'], algorithms=['RS256'])

The above should be wrapped in a try: clause, catching jwt.InvalidAudienceError.

I may go back and give python-jose or authlib another shot.

Unrelated aside: for some reason, when I try to import pyjwt, authlib, or python-jose, pylint in VS Code tells me it cannot load any of those modules. But the script runs fine. ĀÆ\_(惄)_/ĀÆ

I immediately confess Iā€™m far from knowledgeable in Python, but I was curious about something, in particular, any reason for not trying whatā€™s in the Python API quickstart? (Auth0 Python API SDK Quickstarts: Authorization)

1 Like

Thatā€™s a pretty darn good question. I mean, Iā€™ve only downloaded and ran the Python quickstart dozens of times ā€¦ why should I bother looking at it for inspiration! :slight_smile: Iā€™m going to go with ā€œit was late, I was tired.ā€

Thanks @jmangelo!

No need to explain, as developers I find that we sometimes subconsciously decide to ignore what later in retrospective seems an obvious alternative. Happens to me all the timeā€¦ the ā€œhow the hell did I not consider this before?ā€ moment.

And although my lack of Python knowledge canā€™t judge which option is best, one nice side-effect of going with the quickstart approach is that you can then ask for more than just guidance as it being in the quickstart means it should work and if it doesnā€™t we :auth0: need to make it work. :slight_smile:

1 Like

Thanks @jmangelo. This might help a lot. In particular the quickstart uses the Authlib module which is what I had been poking at when I first started working on this.

1 Like