How to decode Firebase JWT token in Python

8.8k Views Asked by At

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.

2

There are 2 best solutions below

5
jeffery_the_wind On

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
0
user2111643 On

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