我在这里尝试使用 google OAuth 对我的 Node Express 应用程序中的用户进行身份验证时遇到了麻烦。我可以成功执行 OAuth,它会返回如下响应:
{
access_token: 'token string',
id_token: 'id.string',
expires_in: 3599,
token_type: "Bearer"
}
这一切都有道理,但我一生都无法弄清楚如何解码 JWT。我对这一切都有点缺乏经验,所以这对我来说有点陌生。
按照此处列出的说明进行操作:https://developers.google.com/accounts/docs/OAuth2Login#validatinganidtoken我正在尝试在我的节点应用程序中本地解码 JWT。
我在我的节点环境中安装了https://github.com/hokaccha/node-jwt-simple。
而且我非常确定我需要使用此证书(https://www.googleapis.com/oauth2/v1/certs)在所有这一切中以某种方式对其进行解码,但我在这里有点不知所措。我真的不明白如何将证书获取到我的节点应用程序中,以及如何将其与 node-jwt-simple 一起使用。而且我也不太明白我如何知道何时需要获取新证书,而不是使用缓存的证书。
有这方面经验的人可以帮助我吗?
感谢您的帮助。我现在完全不知所措。
** 更新 **
所以我取得了一些进步......有点。 通过调用 jwt.decode(id_token,certificate,true);我能够成功解码令牌。即使证书 var 是一个空对象 {}。这给我留下了 3 个问题。 1:使用 google 的 url 将证书获取到我的 Express 应用程序的最佳方法是什么? 2:我如何知道何时需要引入它的新版本? 3:似乎为 noVerify (jwt.decode 中的第三个参数)传递 true 是一个糟糕的主意。我怎样才能让它工作而不传递它? 看起来 jwt-simple 可能需要 hs256 并且令牌正在使用 rs256。
再说一次,我在这方面非常缺乏经验,所以我可能在这里偏离了基地。
*** 更新*** 感谢 Nat 的帮助,我才得以成功! 我想我尝试了每一个 JWT 和 JWS 节点模块。我最终得到的结果如下: 我发现我所查看的模块都没有达到我想要的开箱即用的效果。我创建了以下 jwt 解码辅助方法,用于解码 id_token,这样我就可以从标头中获取孩子。
module.exports = {
decodeJwt: function (token) {
var segments = token.split('.');
if (segments.length !== 3) {
throw new Error('Not enough or too many segments');
}
// All segment should be base64
var headerSeg = segments[0];
var payloadSeg = segments[1];
var signatureSeg = segments[2];
// base64 decode and parse JSON
var header = JSON.parse(base64urlDecode(headerSeg));
var payload = JSON.parse(base64urlDecode(payloadSeg));
return {
header: header,
payload: payload,
signature: signatureSeg
}
}
}
function base64urlDecode(str) {
return new Buffer.from(base64urlUnescape(str), 'base64').toString();
};
function base64urlUnescape(str) {
str += Array(5 - str.length % 4).join('=');
return str.replace(/\-/g, '+').replace(/_/g, '/');
}
我正在使用此解码来确定是否需要从以下位置获取新的公共证书:https://www.googleapis.com/oauth2/v1/certs
然后我使用公共证书和node-jws(https://github.com/brianloveswords/node-jws)jws.verify(id_token,cert)来验证签名!
万岁! 再次感谢您在回复中提供的额外解释。这对帮助我理解我想要做什么大有帮助。希望这也能帮助其他人。
从规范的角度来看,您遇到的是【OpenID Connect】。
id_token 是 [JWS] 签名的 [JWT]。在本例中,它是一个“.”。具有三个组成部分的分隔字符串。第一部分是标题。第二个是有效负载。第三个是签名。它们每个都是 Base64url 编码的字符串。
当您解码标头时,您将得到类似以下内容:
{“alg”:“RS256”,“kid”:“43ebb53b0397e7aaf3087d6844e37d55c5fb1b67”}
“alg”表示签名算法为RS256,其定义在[JWA]中。 “kid”表示与用于签名的密钥相对应的公钥的密钥ID。
现在我准备回答您的一些问题:
2:我如何知道何时需要引入它的新版本?
当缓存的证书文件([JWK] 文件)的孩子与标头中的孩子不匹配时,获取新的证书文件。 (顺便说一句,您从中提取证书的 URL 称为 x5u。)
3:似乎为 noVerify 传递 true (jwt.decode 中的第三个参数) 这是一个糟糕的主意。我怎样才能让它工作而不通过它 在?
确实如此。也许您可能想查看另一个库,例如 kjur.github.io/jsjws/ 。
参考文献