【问题标题】:Authenticate to Google API with Node JS使用 Node JS 对 Google API 进行身份验证
【发布时间】:2019-06-03 11:07:01
【问题描述】:

到目前为止,我所拥有的是应用重定向到同意页面。用户接受,然后我将使用有效的授权代码重定向回 l​​ocalhost。据我了解,我需要打另一个电话并将此代码交换为访问令牌。但是,getAccessToken() 不起作用。控制台日志正在返回:

invalid_client
invalid_request

请告诉我需要哪些额外信息。

以下是相关代码:

var { google } = require('googleapis');
var http = require("http");
var request = require('request');

var oauth2Client = new google.auth.OAuth2(
    '<My Client ID>',
    '<My Client Secret>',
    'http://localhost:8080'
);

exports.generateAuthCodeUrl = function () {

    const url = oauth2Client.generateAuthUrl({
        access_type: 'offline',
        scope: 'https://www.googleapis.com/auth/blogger'
    });

    return url;
};


exports.getAccessToken = function (accessCode) {
    var codeOptions = {
        code: accessCode
    }
    oauth2Client.getToken(codeOptions, function (err, tokens) {
        // Now tokens contains an access_token and an optional refresh_token. Save them.
        if (!err) {
            oauth2Client.setCredentials(tokens);
            return tokens;
        }
        console.log(err.message);
    });
};

编辑:总结和什么对我有用

我两次阅读了 pinoyyid 答案中的链接文章,并注意到了他的答案中列出的步骤。列出简单的步骤有助于我更清楚地理解。此外,按照 cmets 中的建议,我删除了 googleapi 库上面提到的错误发生在这个库的代码中)并且只是定期调用必要的端点与request 库。我使用了request,因为它不那么冗长。我最终得到的代码如下所示:

exports.generateAuthCodeUrl = function () {

    var authURL = "https://accounts.google.com/o/oauth2/v2/auth?" +
        "client_id=" + client_id +
        "&scope=" + scope +
        "&redirect_uri=" + redirect_uri +
        "&response_type=" + response_type;

    //redirect to consent page
    return authURL;  
};

exports.getAccessToken = function (x) {
    var postDataUrl = 'https://www.googleapis.com/oauth2/v4/token?' +
        'code=' + x +  //auth code received from the previous call
        '&client_id=' + client_id +
        '&client_secret=' + client_secret +
        '&redirect_uri=' + redirect_uri +
        '&grant_type=' + "authorization_code"

    var options = {
        uri: postDataUrl,
        method: 'POST'
    };

    request(options, function (err, res, body) {
        return body; //returns an object with an access token!!!
    });
};

很高兴我得到了这个工作!非常感谢大家

【问题讨论】:

  • 如果您可以使用 passport.js,请告诉我.. 我可以提供帮助
  • @programoholic 目前正在寻找纯节点答案。但如果我们走特快和护照路线,将来可能会更新。
  • 我的2c,扔掉库,直接调用endpoints。这是获取身份验证代码的一个重定向,然后是一个简单的 REST 调用以将其交换为访问/刷新令牌。如果您有任何问题,可以将您的 http 请求与来自 Google OAuth 游乐场的请求进行比较,看看您遇到了什么问题。
  • @pinoyyid 这听起来确实是个好主意。我会尝试不使用图书馆。
  • 如果有帮助,我已经发布了 Dummy's Guide to Oauth 作为设置步骤的答案。

标签: javascript node.js google-api google-oauth


【解决方案1】:

3-legged Google OAuth 虚拟指南。

从字面上看,您需要知道的所有内容都在此单页 https://developers.google.com/identity/protocols/OAuth2WebServer 上。读两遍,您将成为 OAuth 忍者。总之,它说...

  1. 使用 4 个查询参数构造一个 accounts.google.com 网址:-
    1. client_id 识别您的应用
    2. scope 说出您要求的权限
    3. redirect_uri 告诉 Google 将用户的浏览器重定向到哪里
    4. response_type=code 说你想要一个验证码
  2. 将用户的浏览器重定向到该 URL
  3. 在用户登录时喝杯咖啡,选择他的 Google 帐户并授予权限,直到最终...
  4. 用户的浏览器被重定向回您应用的redirect_uri,查询参数为code,这是一次性验证码
  5. 将身份验证代码发布到 Google 的令牌端点
  6. 解析 JSON 响应以获取访问令牌
  7. 在“authorization: Bearer access_token”http 标头中为您的后续 Google API 请求使用访问令牌

如果您访问https://developers.google.com/oauthplayground/,您可以在线执行这些步骤,查看各种 URL 和响应的样子。

【讨论】:

  • 接受这个作为正确答案,因为它对我帮助最大。谢谢@pinoyyid!
  • 根据您的回答更新了我的帖子。再次感谢,这有帮助。
【解决方案2】:

我写这个库是为了获取用户信息,希望对你有帮助。

'use strict'

const { google } = require('googleapis')
const credentials = require('../configs/config').google

class googleApi {
    constructor(){
        const {client_id, client_secret, redirectUri } = credentials;
        this.oAuth2Client = new google.auth.OAuth2(client_id, client_secret, redirectUri)
    }

    generateUrl(scopes){
        const url = this.oAuth2Client.generateAuthUrl({
            access_type: 'offline',
            scope: scopes.join(' ')
        })
        return url;
    }

    async getUserInfo(code){
        const credentials = await this.oAuth2Client.getToken(code)
        this.oAuth2Client.setCredentials(credentials.tokens);
        const plus = google.plus({
            version: 'v1',
            auth: this.oAuth2Client,
        });
        const data = await plus.people.get({userId: 'me'});
        return data;
    }
}

module.exports = new googleApi();

这是实现:

'use strict'
const googleApi = require('../libs/google');

exports.requestGmailAuth = function (req, res, next){
    let url = googleApi.generateUrl(scopes)
    res.redirect(url);
}

exports.getGmailUserInfo = async function (req, res, next){
    const qs = new url.URL(req.url, 'http://localhost:3000').searchParams;
    let code = qs.get('code')
    if(!code){
        next(new Error('No code provided'))
    }
    googleApi.getUserInfo(code)
        .then(function(response){
            res.send(response.data)
        }).catch(function(e){
            next(new Error(e.message))
    })
}

这些是路线:

app.get('/request/gmail/auth', user.requestGmailAuth)
app.get('/get/gmail/user', user.getGmailUserInfo)

当 /request/gmail/auth 收到请求时,它会重定向到同意页面,然后同意页面会使用“code”参数重定向到 /get/gmail/user。

试试这个片段,如果问题仍然存在,请检查您的客户端 ID 和客户端密码,并确保您在开发者仪表板中启用了 google plus api。

【讨论】:

  • 我认为这是一个干净的实现。我过去使用过非常相似的东西。但我有一个问题。您如何注销用户?因为在浏览器中,特别是 chrome,我认为,一旦用户登录 Google,ID 就会持续存在,因此这将自动登录该用户并跳过选择不同 ID 的选项。
猜你喜欢
  • 1970-01-01
  • 2013-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-04
  • 2017-03-11
  • 2017-04-03
  • 1970-01-01
相关资源
最近更新 更多