【问题标题】:How can I decode a google OAuth 2.0 JWT (OpenID Connect) in a node app?如何在节点应用程序中解码 google OAuth 2.0 JWT (OpenID Connect)?
【发布时间】:2013-12-08 05:08:16
【问题描述】:

我在这里尝试使用 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:使用谷歌的 url 将证书放入我的 express 应用程序的最佳方法是什么? 2:我怎么知道什么时候需要引入它的新版本? 3:似乎为 noVerify (jwt.decode 中的第三个参数)传递 true 是一个糟糕的主意。如果不通过它,我怎样才能让它工作? 看起来 jwt-simple 可能期待 hs256 并且令牌正在使用 rs256。

再说一次,我在这方面非常缺乏经验,所以我在这里可能有点离谱。

* 更新 * 感谢 Nat 的帮助,我得以完成这项工作! 我想我尝试了每一个 JWT 和 JWS 节点模块。我最终登陆的内容如下: 我发现我看到的所有模块都没有达到我想要的开箱即用的效果。我创建了以下用于解码 id_token 的 jwt 解码辅助方法,因此我可以从标题中获取孩子。

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(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) 来验证签名!

万岁! 再次感谢您在回复中提供的额外解释。这在帮助我理解我什至试图做的事情方面大有帮助。希望这对其他人也有帮助。

【问题讨论】:

    标签: node.js express google-oauth google-openid jwt


    【解决方案1】:

    从规范的角度来看,您遇到的是[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/ 。

    参考文献

    • [OpenID 连接] openid.bitbucket.org/openid-connect-core-1_0.html
    • [JWS] tools.ietf.org/html/draft-ietf-jose-json-web-signature
    • [JWT] tools.ietf.org/html/draft-ietf-oauth-json-web-token‎
    • [JWK] tools.ietf.org/html/draft-ietf-oauth-json-web-keys
    • [JWA] tools.ietf.org/html/draft-ietf-jose-json-web-algorithms

    【讨论】:

    • 太棒了!非常感谢您的彻底和详细的解释。这极大地帮助了我理解我什至试图做的事情。现在我知道如果我还有其他问题应该寻找什么。我真的很感激。
    • 您说“当您解码标头时”,但我想知道:有没有一种简单的方法可以在前端仅使用 JavaScript 来“解码”id_token
    • 很好的答案!我还发现这篇文章非常有趣:darutk.medium.com/understanding-id-token-5f83f50fa02e
    猜你喜欢
    • 2019-11-05
    • 2020-06-13
    • 1970-01-01
    • 2023-03-13
    • 2014-08-28
    • 2015-12-11
    • 2014-06-26
    • 1970-01-01
    • 2019-05-10
    相关资源
    最近更新 更多