Python中如何验证Google Hangouts API传入请求的Bearer授权令牌
Google Hangouts 机器人请求身份校验正确方案
此前校验方式失效原因
你参考的普通用户登录态校验方案不适用于Hangouts机器人场景:Hangouts向你的服务推送请求时携带的Bearer令牌是Google服务端签发的专属服务间交互JWT,和普通用户OAuth登录的id_token签发规则、校验规则完全不同,直接调用通用的id_token校验接口自然无法通过。
正确校验实现步骤
- 第一步:安装依赖
google-auth库,这是Google官方提供的Python身份校验工具pip install google-auth - 第二步:从请求头提取令牌,完成核心字段校验,必须同时满足以下规则:
- JWT签名由Google官方私钥签发,验签使用Google公开的公钥
- 签发者
iss固定为chat@system.gserviceaccount.com - 受众
aud为你的机器人所属的Google Cloud项目的数字ID,需和你创建Hangouts机器人的项目ID完全一致 - 令牌未超出有效期
适配你的Tornado服务的代码示例
import json import tornado.web from google.oauth2 import id_token from google.auth.transport import requests # 替换为你自己的Google Cloud项目数字ID GCLOUD_PROJECT_NUMBER = "你的项目数字ID" class incomingRequestHandler(tornado.web.RequestHandler): def post(self): # 第一步:校验请求身份 auth_header = self.request.headers.get("Authorization", "") if not auth_header.startswith("Bearer "): self.set_status(401) self.write({"error": "Unauthorized"}) return bearer_token = auth_header.split(" ")[1] try: # 校验JWT令牌 id_info = id_token.verify_token( bearer_token, requests.Request(), audience=GCLOUD_PROJECT_NUMBER ) # 额外校验签发者是否为Hangouts官方 if id_info["iss"] != "chat@system.gserviceaccount.com": raise ValueError("Invalid issuer") except Exception as e: self.set_status(401) self.write({"error": "Invalid token"}) return # 校验通过后再执行业务逻辑 recievedData = json.loads(self.request.body.decode('utf-8')) responseData = generateResponse(recievedData) self.write({ 'text' : responseData })
补充说明
如果要使用公网接口校验的方式也可生效,需要注意拿到Bearer令牌后调用接口时不要误传为id_token参数,部分场景下返回的字段结构和普通用户登录令牌不同,校验时需要手动核对iss和aud字段是否符合要求,不推荐这种方式,本地验签性能和安全性更高。
内容的提问来源于stack exchange,提问作者Maurice Kasomwung
相关产品推荐
相关产品推荐

