从 Google Chat POST 请求验证 JWT

Posted

技术标签:

【中文标题】从 Google Chat POST 请求验证 JWT【英文标题】:Verify JWT from Google Chat POST request 【发布时间】:2019-09-05 22:31:23 【问题描述】:

我有一个使用 HTTPs 端点连接到 Google Chat 的 NodeJS 机器人。我正在使用快递接收请求。我需要验证所有请求都来自 Google,并希望使用 Google 随请求发送的承载令牌来执行此操作。

我的问题是我正在努力寻找验证令牌的方法。

我已捕获令牌并尝试对https://oauth2.googleapis.com/tokeninfo?id_token=ey... 进行 GET 请求(其中 ey... 是令牌开始)。

返回:

    "error": "invalid_token",
    "error_description": "Invalid Value"

我已经尝试过 Google 推荐的方法:

var token = req.headers.authorization.split(/[ ]+/);
client.verifyIdToken(
    idToken: token[1],
    audience: JSON.parse(process.env.valid_client_ids)
).then((ticket) => 
    gchatHandler.handleGChat(req.body, res);
).catch(console.error);

并得到以下错误:

错误:找不到信封的 pem:"alg":"RS256","kid":"d...1","typ":"JWT"

知道我应该从这里去哪里吗?

编辑:https://www.googleapis.com/service_accounts/v1/metadata/x509/chat@system.gserviceaccount.com 发现了这个,正在研究如何使用它。这个孩子和我得到的那个很相配。

【问题讨论】:

【参考方案1】:

上述解决方案可能适用于 Google Chat,但根据我的经验,Google 服务(例如 Google Tasks)使用 OIDC 令牌,可以使用 verifyIdToken 函数进行验证。

在此处添加我的解决方案,因为您的问题/答案是我能找到的最接近我的问题的东西

所以,如果您需要使用自己的代码签署请求

在客户端,使用 OIDC 令牌发送请求

import URL from 'url';
import GoogleAuth from 'google-auth-library'; 

// will use default auth or GOOGLE_APPLICATION_CREDENTIALS path to SA file
// you must validate email of this identity on the server!
const auth = new GoogleAuth();

export const request = async (url, ...options) => 
  const targetAudience = new URL(url as string).origin;
  const client = await auth.getIdTokenClient(targetAudience);
  return await client.request(...options, url);
;

await request( url: 'https://my-domain.com/endpoint1', method: 'POST', data:  )

在服务器上,验证 OIDC(Id 令牌)


const auth = new OAuth2Client();

const audience = 'https://my-domain.com';


// to validate
const token = req.headers.authorization.split(/[ ]+/)[1];
const ticket = await auth.verifyIdToken(idToken: token, audience );

if (ticket.getPayload().email !== SA_EMAIL) 
 throw new Error('request was signed with different SA');

// all good

阅读更多关于Google OpenID Connect Tokens

【讨论】:

【参考方案2】:

最终解决了。

您需要点击:https://www.googleapis.com/service_accounts/v1/metadata/x509/chat@system.gserviceaccount.com 以获取一个 JSON 文件,其中包含链接到其 KID 的密钥。

然后当请求到达时,使用 jsonwebtoken (NPM) 对 token 进行解码并从 header 中提取 KID。

使用 KID 在上述网站的响应中找到匹配的公钥,然后使用验证功能确保令牌与公钥匹配。

您还需要传递受众和颁发者选项以进行验证,以验证是您的特定服务帐户击中了机器人。

【讨论】:

以上是关于从 Google Chat POST 请求验证 JWT的主要内容,如果未能解决你的问题,请参考以下文章

Google PubSub / Gmail Webhook:发送电子邮件时始终从 PubSub 接收多个 POST 请求

请求的身份验证范围不足 - 在 Flutter 中使用 Firebase 从 Google 登录获取生日时出错

Google App Script Web App GET 和 POST 请求被 CORS 策略阻止

如何使用python请求将经过身份验证的POST请求编码到API?

使用 POST 的 Google App Engine Cron 请求

从 React 向 Django 发送 post 请求时出现 400(错误请求)