【问题标题】:How to verify google auth token at server side in node js?如何在节点 js 的服务器端验证谷歌身份验证令牌?
【发布时间】:2017-07-13 07:49:07
【问题描述】:

我的前端应用程序使用 gmail 帐户进行了身份验证

我在验证成功后检索 id_token 并将其作为 Authorization Header 作为 bearer token 发送。

例如 http://localhost:4000/api

授权持有者token_id

nodejs服务器端,我调用下面的方法来验证token。

exports.verifyUser = function(req, res, next) {
    var GoogleAuth = require('google-auth-library');
    var auth = new GoogleAuth();
    var client = new auth.OAuth2(config.passport.google.clientID, config.passport.google.clientSecret, config.passport.google.callbackURL);
    // check header or url parameters or post parameters for token
    var token = "";
    var tokenHeader = req.headers["authorization"];
    var items = tokenHeader.split(/[ ]+/);
    if (items.length > 1 && items[0].trim().toLowerCase() == "bearer") {
        token = items[1];
    }
    if (token) {
        var verifyToken = new Promise(function(resolve, reject) {
            client.verifyIdToken(
                token,
                config.passport.google.clientID,
                function(e, login) {
                    console.log(e);
                    if (login) {
                        var payload = login.getPayload();
                        var googleId = payload['sub'];
                        resolve(googleId);
                        next();
                    } else {
                        reject("invalid token");
                    }
                }
            )
        }).then(function(googleId) {
            res.send(googleId);
        }).catch(function(err) {
            res.send(err);
        })
    } else {
        res.send("Please pass token");
    }
}

当我调用上述方法时,我总是得到 Invalid token 响应并出现以下错误。

Error: No pem found for envelope:     {"alg":"RS256","kid":"c1ab5857066442ea01a01601
850770676460a712"}
    at OAuth2Client.verifySignedJwtWithCerts (\node_modules\google-auth-libr
ary\lib\auth\oauth2client.js:518:13)
  • 这是验证令牌的正确方法吗?
  • 我是否将 id_token 作为授权承载发送?还是只是为了授权?
  • 如何将 id_token 发送到服务器端?通过网址,标题?
  • 我做错了什么?

非常感谢任何帮助。

【问题讨论】:

    标签: javascript node.js api google-signin google-authentication


    【解决方案1】:

    OAuth2Client.verifyIdTokenlibrary source 获取一个 idToken 参数:

    /**
     * Verify id token is token by checking the certs and audience
     * @param {string} idToken ID Token.
     * @param {(string|Array.<string>)} audience The audience to verify against the ID Token
     * @param {function=} callback Callback supplying GoogleLogin if successful
     */
    OAuth2Client.prototype.verifyIdToken = function(idToken, audience, callback)
    

    您已经传递了整个标头值bearer eyJhbGciOiJSUzI1NiIsImtpZCI6ImMxYWI1OD U3MDY2NDQyZWEwMWEwMTYwMTg1MDc3MDY3NjQ2MGE3MTIifQ,因此您必须将标头值拆分为:

    var authorization = req.headers["authorization"];
    var items = authorization.split(/[ ]+/);
    
    if (items.length > 1 && items[0].trim() == "Bearer") {
        var token = items[1];
        console.log(token);
        // verify token
    }
    

    这是验证令牌的正确方法吗?

    是的,这是验证令牌的正确方法。对于调试,如果您有任何疑问或快速测试,您还可以使用 tokeninfo 端点验证令牌:

    https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=XYZ123
    
    • 我是否将 id_token 作为授权承载发送?或者是为了 仅授权?
    • 如何将 id_token 发送到服务器端?直通 网址,标题?

    您可以在 Authorization 标头中发送 JWT 令牌,但它可能会导致您拥有 multiple Authorization headers 的用例。最好在正文中进行 URL 编码或嵌入令牌。你可以查看谷歌示例here

    此外,Google 要求以下内容:

    • 令牌必须通过 HTTPS POST 发送
    • 必须验证令牌完整性

    要优化您的代码,您还可以将您的 Google auth 对象移动到您应用根目录下的 app.js,而不是在每次验证令牌时重新定义它。在app.js

    var app = express();
    
    var GoogleAuth = require('google-auth-library');
    var auth = new GoogleAuth();
    app.authClient = new auth.OAuth2(config.passport.google.clientID, config.passport.google.clientSecret, config.passport.google.callbackURL);
    

    verifyUser 中从req.app.authClient 调用它:

    req.app.authClient.verifyIdToken(...)
    

    【讨论】:

    • 请您在帖子中回答我的其他问题吗?
    • "你可以在 Authorization 标头中发送 JWT 令牌,没问题" -> 但这不是授权标头,它是用于身份验证的,我认为方法不同。如果有人必须同时发送(身份验证和授权)怎么办?
    • 你是对的,因为multiple authorization header 是有争议的,尽管我可能会更新使用 URL 编码或嵌入在正文中。感谢您指出
    • 我认为您不能将embedded in the body 发送给get request
    • 不能使用GET请求,必须是POST check this
    【解决方案2】:

    我今天终于找到了答案。 Firebase 工具会将原生 Google 连接到第三方登录令牌,然后再封装另一层。此时获得的token不再是谷歌给我们的原始token。

    • A1:
      • 原始令牌:GoogleDesignInAccount Account = Task.getResult(ApiException.class);
      • Account.getidToken () // This is the original token
    • B1:
      • Firebase 令牌:FireBaseUser currentUser = Mauth.getCurrentUser ();
      • String token = currentUser.getIdToken(false).getResult().getToken();
    • A2:
      • Google 官方提供了验证令牌的方法
    • B2:
      • Firebase 官方提供了身份验证令牌方法

    我们为上述四个数据点使用代号。如果需要在后台验证token的有效性,它们必须相互对应,A1到A2,B1到B2。如果你使用 A2 来验证 B1,它会失败

    【讨论】:

    • 感谢您的回答,但能否请您将图片中的内容作为文字发布在您的回答中,以确保即使图片被删除,该回答仍然有用?
    猜你喜欢
    • 1970-01-01
    • 2022-08-16
    • 1970-01-01
    • 2017-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-11
    • 2012-06-05
    相关资源
    最近更新 更多