Over on GitHub a helpful Google dev told me that
to create a user session, your python backend server only needs a JWT
library to verify the Firebase Auth token (signature and audience) in
the request and extract the user info from the token payload.
mFirebaseAuth.getCurrentUser().getToken(false).getResult().getToken()
user_id
identity-toolkit-python-client
python-jose
python-jose
GitKit.VerifyGitkitToken()
jose.jwt.get_unverified_header()
jose.jwt.get_unverified_claims()
jose.jwt.decode()
jose.jwt.decode(token, key, algorithms=None, options=None, audience=None, issuer=None, subject=None, access_token=None)
verify the Firebase Auth token (signature and audience)
The keys can be obtained
for Firebase at
https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com
and for Gitkit at
https://www.googleapis.com/identitytoolkit/v3/relyingparty/publicKeys
Using Googles oauth2client
library makes the verification very easy.
But if you want to use python-jose
, then you first need to convert the PEM certificate into an RSA public key. This public key is then the key that needs to be used. And the audience should not be extracted from the JWT header, but hard coded into the source code, where in Firebase the audience is the project id and in Gitkit it is one of the OAuth 2.0 client IDs which can be found in the Google Developer Console Credentials section.
The kid
in the JWT header is used to select the appropriate certificate which will be used to obtain the key used to perform the verification.
# firebase
# target_audience = "firebase-project-id"
# certificate_url = 'https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com'
# gitkit
target_audience = "123456789-abcdef.apps.googleusercontent.com" # (from developer console, OAuth 2.0 client IDs)
certificate_url = 'https://www.googleapis.com/identitytoolkit/v3/relyingparty/publicKeys'
response = urllib.urlopen(certificate_url)
certs = response.read()
certs = json.loads(certs)
print "CERTS", certs
print ''
print ''
# -------------- verify via oauth2client
from oauth2client import crypt
crypt.MAX_TOKEN_LIFETIME_SECS = 30 * 86400 # according to https://github.com/google/identity-toolkit-python-client/blob/master/identitytoolkit/gitkitclient.py
print "VALID TOKEN", crypt.verify_signed_jwt_with_certs(idtoken, certs, target_audience)
print ''
print ''
# -------------- verify via python-jose
from jose import jwt
unverified_header = jwt.get_unverified_header(idtoken)
print "UNVERIFIED HEADER", unverified_header
print ''
print ''
unverified_claims = jwt.get_unverified_claims(idtoken)
print "UNVERIFIED CLAIMS", unverified_claims
print ''
print ''
from ssl import PEM_cert_to_DER_cert
from Crypto.Util.asn1 import DerSequence
pem = certs[unverified_header['kid']]
der = PEM_cert_to_DER_cert(pem)
cert = DerSequence()
cert.decode(der)
tbsCertificate = DerSequence()
tbsCertificate.decode(cert[0])
rsa_public_key = tbsCertificate[6]
print "VALID TOKEN", jwt.decode(idtoken, rsa_public_key, algorithms=unverified_header['alg'], audience=target_audience)