【问题标题】:iOS & node.js: how to verify passed access token?iOS & node.js:如何验证通过的访问令牌?
【发布时间】:2012-08-10 02:04:43
【问题描述】:

我有一个 iOS,它使用 OAuth 和 OAuth2 提供程序(Facebook、google、twitter 等)来验证用户并提供访问令牌。除了姓名和电子邮件地址等最少数据外,该应用不会将这些服务用于身份验证之外的任何事情。

然后应用程序将访问令牌发送到服务器以指示用户已通过身份验证。

服务器是用 Node.js 编写的,在执行任何操作之前,它需要根据正确的 OAuth* 服务验证提供的访问令牌。

我一直在环顾四周,但到目前为止,我发现的所有 node.js 身份验证模块似乎都是用于通过服务器提供的网页进行登录和身份验证的。

有谁知道任何可以对提供的访问令牌进行简单验证的 node.js 模块?

【问题讨论】:

    标签: node.js authentication oauth


    【解决方案1】:

    据我所知(并且据我通过阅读规范可知),OAuth 和 OAuth 2 规范没有为访问令牌验证指定单个端点。这意味着您将需要为每个提供者自定义代码来仅验证访问令牌。

    我查找了如何处理您指定的端点:

    脸书

    似乎others 使用了 Facebook 的图形 API 的 'me' endpoint 来检查令牌是否有效。基本上,请求:

    https://graph.facebook.com/me?access_token={accessToken}
    

    谷歌

    Google 有一个dedicated debugging endpoint 用于获取访问令牌信息,还有nice documentation。基本上,请求:

    https://www.googleapis.com/oauth2/v1/tokeninfo?access_token={accessToken}
    

    但是,他们建议您不要在生产环境中这样做:

    tokeninfo 端点对调试有用,但对生产有用 目的,从密钥端点检索 Google 的公钥,并 在本地执行验证。您应该从中检索密钥 URI Discovery document 使用 jwks_uri 元数据值。请求 调试端点可能会受到限制或以其他方式受制于 间歇性错误。

    由于 Google 很少更改其公钥,因此您可以缓存 他们使用 HTTP 响应的缓存指令,并且在广大的 大多数情况下,执行本地验证比 通过使用 tokeninfo 端点。此验证需要检索 和解析证书,并进行适当的加密 调用检查签名。还好有调试好的 提供多种语言的库来实现这一目标 (见 jwt.io)。

    推特

    Twitter 似乎没有一个非常明显的方法来做到这一点。我怀疑因为account settings data 是相当静态的,这可能是最好的验证方式(获取推文可能会有更高的延迟?),所以您可以请求(使用适当的 OAuth 签名等):

    https://api.twitter.com/1.1/account/settings.json
    

    请注意,此 API 的速率限制为每个窗口 15 次。

    总而言之,这似乎比最初看起来更棘手。在服务器上实现某种会话/身份验证支持可能是一个更好的主意。基本上,您可以验证一次获得的外部 OAuth 令牌,然后为用户分配一些您自己的会话令牌,您可以使用该会话令牌在您自己的服务器上使用用户 ID(电子邮件、FB id 等)进行身份验证,而不是继续制作为您自己收到的每个请求向 OAuth 提供者发出请求。

    希望有帮助!

    【讨论】:

    • 如何在微软和LinkedIn中做到这一点?
    • @lincx 你知道如何在 LinkedIn 中操作吗?
    • 这在 2018 年仍然适用吗?
    【解决方案2】:

    对于生产环境中的 google,安装 google-auth-library (npm install google-auth-library --save) 并使用以下命令:

    const { OAuth2Client } = require('google-auth-library');
    const client = new OAuth2Client(GOOGLE_CLIENT_ID); // Replace by your client ID
    
    async function verifyGoogleToken(token) {
      const ticket = await client.verifyIdToken({
        idToken: token,
        audience: GOOGLE_CLIENT_ID  // Replace by your client ID 
      });
      const payload = ticket.getPayload();
      return payload;
    }
    
    router.post("/auth/google", (req, res, next) => {
      verifyGoogleToken(req.body.idToken).then(user => {
        console.log(user); // Token is valid, do whatever you want with the user 
      })
      .catch(console.error); // Token invalid
    });
    

    更多关于Authenticate google token with a backend server的信息,可以找到node.js、java、python和php的例子。

    对于 Facebook,执行如下 https 请求:

    const https = require('https');
    
    router.post("/auth/facebook", (req, res, next) => {
    
      const options = {
        hostname: 'graph.facebook.com',
        port: 443,
        path: '/me?access_token=' + req.body.authToken,
        method: 'GET'
      }
    
      const request = https.get(options, response => {
        response.on('data', function (user) {
          user = JSON.parse(user.toString());
          console.log(user);
        });
      })
    
      request.on('error', (message) => {
        console.error(message);
      });
    
      request.end();
    })
    

    【讨论】:

      【解决方案3】:

      在 Google 的生产环境中,您可以使用:

      https://www.npmjs.com/package/google-auth-library

      const ticket = client.verifyIdToken({
          idToken: ctx.request.body.idToken,
          audience: process.env.GOOGLE_CLIENTID
      })
      

      【讨论】:

        【解决方案4】:

        要从 Google 获取有关令牌的信息,请小心使用版本 api https://www.googleapis.com/oauth2/v3/tokeninfo?access_token={accessToken}

        【讨论】:

          猜你喜欢
          • 2019-08-08
          • 2021-10-04
          • 1970-01-01
          • 1970-01-01
          • 2020-05-26
          • 2012-01-26
          • 2016-09-04
          • 2022-10-15
          • 2015-07-16
          相关资源
          最近更新 更多