我正在使用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)