使用google python端点进行firebase身份验证

时间:2016-07-22 07:43:50

标签: google-app-engine google-cloud-endpoints jwt firebase-authentication pycrypto

我正在使用firebase身份验证集成联合登录,并且我在google appengine端点和正在访问的其他服务器上安装了REST API。

从概念上讲,用户通过firebase登录google登录,角网络客户端使用firebase客户端库获取id令牌并将其发送到google端点。谷歌端点验证id令牌以授予访问权限。

在阅读并完成各种文章之后,我终于有了一些工作,但是我在这个授权领域的经验很少,并且想知道是否有更好的方法来做到这一点。

get the id token on the client side的代码是

firebase.auth().currentUser.getToken(true).then(function(idToken) {
   // Send token to your backend via HTTPS
}

此代码有效,我获得了正确的ID令牌。

现在我正在使用postman将此id令牌发送到授权标头中的app引擎端点。

Google appengine端点代码

# only showing imports specifically required for cryptography 
import jwt
import jwt.algorithms

from jwt.contrib.algorithms.pycrypto import RSAAlgorithm
jwt.register_algorithm('RS256', RSAAlgorithm(RSAAlgorithm.SHA256))

logging.debug("algorithms = ", jwt.algorithms.get_default_algorithms())

#had to install pyjwt as a library in appengine https://cloud.google.com/appengine/docs/python/tools/using-libraries-python-27

import json
import base64

from Crypto.Util.asn1 import DerSequence
from Crypto.PublicKey import RSA
from binascii import a2b_base64

import httplib


""" Message to accept a JWT for access """
class UserJWTMsg(messages.Message):
    token = messages.StringField(1)

class UserMsg(messages.Message):
    name = messages.StringField(1)

# [START user_api]
@endpoints.api(name='user', version='v1')
class UserApi(remote.Service):

    """ Access with id Token """
    @endpoints.method(
        message_types.VoidMessage,
        UserMsg,
        path='access-with-idToken',
        http_method='GET',
        name='access-with-idToken')
    def access_with_id_token(self, request):
      id_token = self.request_state.headers.get('authorization')

      id_token_parts = id_token.split('.')

      #get key id from the token header
      #check if padding needs to be added to the id token header
      padding_count = 4 - len(id_token_parts[0])%4
      if padding_count:
        id_token_header = id_token_parts[0] + b'='*padding_count

      #decode base64 header
      decoded_id_token_header_json = base64.b64decode(id_token_header)
      decoded_id_token_header = json.loads(decoded_id_token_header_json)

      #get key id from the header
      key_id = decoded_id_token_header['kid']

      #get certificate for the given key id, #cert = CERTS.get(key_id)
      cert = getCertificate(key_id)

      #get the public key from certificate
      public_key = pubKeyFrmCert(cert)

      #decode / verify id token
      decoded_payload = jwt.decode(id_token, public_key, audience='audience')

      return UserMsg(name=json.dumps(decoded_payload));


""" get Certificate for key id """
def getCertificate(key_id):

    c =       httplib.HTTPSConnection("www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com")
    c.request("GET", "/")

    response = c.getresponse()

    cert_str = response.read()
    cert_obj = json.loads(cert_str)
    cert = cert_obj.get(key_id)

    return(cert)


""" return a public key from a X509 certificate """
""" http://stackoverflow.com/questions/12911373/how-do-i-use-a-x509-certificate-with-pycrypto """
def pubKeyFrmCert(cert):

    lines = cert.replace(" ",'').split()
    der = a2b_base64(''.join(lines[1:-1]))

    # Extract subjectPublicKeyInfo field from X.509 certificate (see RFC3280)
    cert = DerSequence()
    cert.decode(der)
    tbsCertificate = DerSequence()
    tbsCertificate.decode(cert[0])
    subjectPublicKeyInfo = tbsCertificate[6]

    # Initialize RSA key
    rsa_key = RSA.importKey(subjectPublicKeyInfo)

    return(rsa_key)

0 个答案:

没有答案