How to decode Firebase JWT token in Python
Asked Answered
F

2

10

I have added Firebase to allow clients to authenticate directly from the web app client (browser). I am using the firebase-web JS package and it works great. I can see in my browser that I receive a user object with information about the user, including an idToken.

I need to then authenticate this user on my server backend, which is python django. In the Firebase docs I found a how-to for exactly what I am trying to do, which is to verify the id token.

Since they don't have the supported Firebase sdk for python, I need to use a third party solution. I have come to the python-jose package after finding it listed on the jwt.io site. The example looks simple enough:

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

This is my first time using JWT. I don't know what to use for the 'secret'. I tried pasting my id token as token, and the web API key from the Firebase console for secret, but got this error:

jose.exceptions.JWKError: RSA key format is not supported

I also tried the JWT debugger, which seems to be reading most of my id token correctly, but the signature verification is looking for a public and/or a private keys, which like the 'secret' are escaping me.

enter image description here

I am really at a loss for how to find this secret, and how to verify the JWT id token in general. The information on the Firebase docs (third-party section) is:

Finally, ensure that the ID token was signed by the private key corresponding to the token's kid claim. Grab the public key from https://www.googleapis.com/robot/v1/metadata/x509/[email protected] and use a JWT library to verify the signature. Use the value of max-age in the Cache-Control header of the response from that endpoint to know when to refresh the public keys.

I have tried pasting the whole json blob from that googleapis url into the JWT debugger, but still getting an "invalid signature" alert. I don't understand how to use that public key.

Should python-jose work for this approach? If so, what should I use for the secret? If not, can someone point me in the right direction?

Thanks.

Frisch answered 28/11, 2016 at 8:25 Comment(3)
Hey Jeffery, I just did a Google search and came across the following library: codegists.com/snippet/python/… I have not checked it but it is worth take a look at.Arly
I cannot vouch for the above library's security. Use it at you own risk. The best place to get guidance on this is the official docs: firebase.google.com/docs/auth/admin/…Arly
Thank you, I actually figured out how to use the python-jose package, I will post an answer.Frisch
F
13

I finally found the answer I was looking for in this post: Migrating Python backend from Gitkit to to Firebase-Auth with python-jose for token verification

Since the time of the post there have been updates made to the python-jose package, which gives better support for firebase id tokens. Here is some working code ( jose version 1.3.1 ) on how to use python to decode the firebase id token:

import urllib, json
from jose import jwt

idtoken = "<id token passed to server from firebase auth>"

target_audience = "<firebase app id>"

certificate_url = 'https://www.googleapis.com/robot/v1/metadata/x509/[email protected]'

response = urllib.urlopen(certificate_url)
certs = response.read()
certs = json.loads(certs)

#will throw error if not valid
user = jwt.decode(idtoken, certs, algorithms='RS256', audience=target_audience)
print user
Frisch answered 28/11, 2016 at 21:25 Comment(5)
Thanks for the example @jeffery_the_wind, I think the current python-jose has changed the API again and has no certs equivalent, instead only asks for a key (python-jose.readthedocs.io/en/latest/jwt/api.html) is this still working?Chokeberry
With Version 1.3.2 I get this error with a similar run: "jose.exceptions.JWKError: RSA key format is not supported"Chokeberry
Thanks @Chokeberry I updated the answer with the working jose package version. I will look at the new package to see how it was changed.Frisch
Also I am testing with AWS Cognito JWT, so maybe it's just the contents of the decode certs that need extra converting.Chokeberry
I found out the error was due to trying to use the key value ('n'), in AWS the certs come as JSON dicts and can be passed directly to jwt.decode as the key - This is different to the googleapis certsChokeberry
S
2

The response above is good just use this certificate URL instead to get the right format expected by the JOSE jwt.decode

import urllib, json
from jose import jwt
idtoken = "<id token passed to server from firebase auth>"
target_audience = "<firebase app id>"
 # this line updated 
certificate_url = 'https://www.googleapis.com/service_accounts/v1/jwk/[email protected]'

response = urllib.urlopen(certificate_url)
certs = response.read()
certs = json.loads(certs)

#will throw error if not valid
user = jwt.decode(idtoken, certs, algorithms='RS256',     audience=target_audience)
print user
Sprouse answered 7/11, 2023 at 19:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.