Аутентификация в Google API с помощью Node JS

Пока что у меня есть приложение перенаправляет на страницу согласия. Пользователь принимает, затем я перенаправлен обратно на локальный хост с действительным кодом авторизации. Из того, что я понимаю, мне нужно сделать еще один звонок и обменять этот код на токен доступа. 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 ДВАЖДЫ и также отметил шаги, перечисленные в его ответе. Перечисление простых шагов помогло мне понять более ясно. Кроме того, как было рекомендовано в комментариях, я удалил библиотеку 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!!!
    });
};

Очень рад, что я получил это работает! Большое спасибо всем вам

Ответы

Ответ 1

Манекен Руководство по 3-х ноги Google OAuth.

Буквально все, что вам нужно знать, находится на этой единственной странице https://developers.google.com/identity/protocols/OAuth2WebServer. Прочитайте его дважды, и вы станете ниндзя OAuth. В целом, это говорит...

  1. Создайте URL-адрес account.google.com с 4 параметрами запроса: -
    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. Используйте токен доступа в заголовке http "authorization: bearer access_token" для последующих запросов API Google

Если вы перейдете по адресу https://developers.google.com/oauthplayground/, вы можете выполнить онлайн-шаги, чтобы увидеть, как выглядят различные URL-адреса и ответы.

Ответ 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 получает запрос, он перенаправляет на страницу согласия, тогда страница согласия перенаправляет на /get/gmail/user с параметром "code".

попробуйте этот фрагмент, и если проблема не исчезнет, проверьте свой идентификатор клиента и секрет клиента, а также убедитесь, что у вас включен Google Plus API на панели инструментов разработчика.