简体   繁体   English

使用Gitkit将Python后端从Gitkit迁移到Firebase-Auth,以进行令牌验证

[英]Migrating Python backend from Gitkit to to Firebase-Auth with python-jose for token verification

Over on GitHub a helpful Google dev told me that 在GitHub上,一个有用的Google开发人员告诉我,

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. 要创建用户会话,您的python后端服务器仅需要一个JWT库来验证请求中的Firebase Auth令牌(签名和受众)并从令牌有效载荷中提取用户信息。

I am having trouble with verifying the token. 我在验证令牌时遇到了麻烦。

This is where I'm at; 我在这里 In order to start the migration I proceeded as follows: 为了开始迁移,我进行了如下操作:

  1. I added Firebase-Auth to the Android App, while still having Gitkit in the App until Firebase-Auth works. 我将Firebase-Auth添加到了Android应用程序中,而在Firebase-Auth工作之前,该应用程序中仍包含Gitkit。 Now I have two sign-in buttons, one which signs in into Firebase and one for the "almost deprecated" Gitkit. 现在,我有两个登录按钮,一个用于登录Firebase,另一个用于“几乎已弃用”的Gitkit。

  2. On firebase.com I imported the Google project into a new Firebase Project, so the user database is the same. 在firebase.com上,我将Google项目导入了新的Firebase项目,因此用户数据库是相同的。 I've already managed to use Firebase-Auth in the Android App, am able to log-in as a known user and I can successfully retrieve the token which I will need for my backend server by calling mFirebaseAuth.getCurrentUser().getToken(false).getResult().getToken() . 我已经设法在Android App中使用Firebase-Auth,能够以已知用户身份登录,并且可以通过调用mFirebaseAuth.getCurrentUser().getToken(false).getResult().getToken()成功检索后端服务器所需的令牌mFirebaseAuth.getCurrentUser().getToken(false).getResult().getToken() It contains the same user_id as the GitKit token. 它包含与GitKit令牌相同的user_id

Now I'm attempting to replace the identity-toolkit-python-client library with python-jose . 现在,我尝试用python-jose替换identity-toolkit-python-client库。 Since I'm currently not sending the Firebase token to the backend, but only the Gitkit token, I want to test this python-jose library on the Gitkit token. 由于我目前不将Firebase令牌发送到后端,而仅发送到Gitkit令牌,因此我想在Gitkit令牌上测试此python-jose库。

On the backend, before calling GitKit.VerifyGitkitToken() i'm now printing out the results of jose.jwt.get_unverified_header() and jose.jwt.get_unverified_claims() in order to check if I get to see what I expect. 在后端,在调用GitKit.VerifyGitkitToken()之前,我现在打印出jose.jwt.get_unverified_header()jose.jwt.get_unverified_claims()的结果,以检查是否可以看到期望的结果。 The results are good, I am able to view the content of the Gitkit token just as expected. 结果很好,我能够按预期查看Gitkit令牌的内容。

My problem comes with the verification. 我的问题来自验证。 I'm unable to use jose.jwt.decode() for verification because I don't know which key I need to use . 我无法使用jose.jwt.decode()进行验证,因为我不知道需要使用哪个密钥

jose.jwt.decode(token, key, algorithms=None, options=None, audience=None, issuer=None, subject=None, access_token=None)

I know the algorithm from the header and an 'aud' field is also stored in the claims, if that is of any help. 我从头知道算法,并且如果有帮助的话,“ aud”字段也存储在声明中。

Getting back to the engineers comment 回到工程师的评论

verify the Firebase Auth token (signature and audience) 验证Firebase身份验证令牌(签名和受众)

How do I do that with the info I have avaliable? 我该如何利用我掌握的信息呢? I guess audience is the 'aud' field in the claims, but how do I check the signature? 我想听众是索赔中的“ aud”字段,但是如何检查签名?

Once I've removed the Gitkit dependency on the server, I will continue with the migration. 删除服务器上的Gitkit依赖关系后,我将继续进行迁移。

From what I've seen, the GitKit library apparently makes an "RPC" call to a Google server for verification, but I may be wrong. 从我所看到的,GitKit库显然对Google服务器进行了“ RPC”调用以进行验证,但是我可能是错的。

So, which will be the key for Gitkit token verification as well as the one for the Firebase token verification? 那么,哪一个将是Gitkit令牌验证的关键,又将是Firebase令牌验证的关键?

The keys can be obtained 可以获取密钥

for Firebase at https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com 用于Firebase, https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.comhttps://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com

and for Gitkit at https://www.googleapis.com/identitytoolkit/v3/relyingparty/publicKeys 对于Gitkit, https://www.googleapis.com/identitytoolkit/v3/relyingparty/publicKeys访问https://www.googleapis.com/identitytoolkit/v3/relyingparty/publicKeys

Using Googles oauth2client library makes the verification very easy. 使用Google的oauth2client库使验证非常容易。

But if you want to use python-jose instead of oauth2client , then you first need to convert the PEM certificate into an RSA public key ( update: this issue got fixed, for Firebase this is now handled by the library, scroll down to the end in the GitHub link preceding this comment. Not sure about Gitkit ). 但是,如果要使用python-jose而不是oauth2client ,则首先需要将PEM证书转换为RSA公钥更新:此问题已解决,对于Firebase,现在由库处理,向下滚动到最后在此评论之前的GitHub链接中。不确定Gitkit )。 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. 而且受众应该从JWT标头中提取出来 ,而应该硬编码到源代码中,在Firebase中,受众是项目ID,而在Gitkit中,受众是可以在Google Developer Console中找到的OAuth 2.0客户端ID之一。凭据部分。

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. JWT标头中的kid用于选择适当的证书,该证书将用于获取用于执行验证的密钥。

  # 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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM