谷歌身份验证挂起等待响应

时间:2019-03-07 12:37:44

标签: node.js firebase google-api google-oauth google-api-nodejs-client

执行日志:

  

内部authorize()函数------------------------
  在readAuth2TokensFromFile()函数内部------------------------
  从文件中读取令牌时出错:./ credentials / token.json   在getNewTokensFromGoogleCLI()函数内部------------------------
  通过访问以下(Google登录)URL:https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&scope= ...
来授权此应用   在getAnswerOn(question)函数内部------------------------

...正在等待Google CLI的响应...

此函数调用readLineInterface的问题:

/**
 * @param {string} query The question to ask.
 */
function getAnswerOn(question) {
  console.log("inside getAnswerOn(question) function ------------------------");
  return new Promise((resolve) => {
    //https://millermedeiros.github.io/mdoc/examples/node_api/doc/readline.html
    const rl = readline.createInterface({
      input: process.stdin,
      output: process.stdout,
    });

    rl.question(question, (answer) => {
      console.log("Answer received succesfully!");
      rl.close();
      process.stdin.destroy();
      resolve(answer);
    });

  })
}

OAuth2Authorizer.js文件的完整源代码:

//Based on https://stackoverflow.com/questions/54882145/is-there-an-async-await-node-js-google-auth-module
//OAuth2Authorizer with Promises
'use strict'
const fs = require('fs');
const readline = require('readline');

const functions = require('firebase-functions');
const { google } = require('googleapis');

//Go to the Google Cloud Dashboard: APIs and Services/ Credentials panel: 
//https://console.cloud.google.com/apis/credentials
//OAuth2 Client Credentials (Other):
const KEY = require("./credentials/oauth2.key.json").web;

/**
* Create a new OAuth2 client with the configured keys.
* https://github.com/googleapis/google-api-nodejs-client
*/
const oauth2Client = new google.auth.OAuth2(
  KEY.client_id,
  KEY.client_secret,
  KEY.redirect_uris[0]
);

function getOAuth2Client() {
  console.log("inside getOAuth2Client ----------------------------");
  return oauth2Client
}


/**
 * reading Tokens from a file:
 * @param {string} path Path to a JSON file where the tokens is stored in.
 */
function readAuth2TokensFromFile(path) {
  console.log("inside readAuth2TokensFromFile() function ------------------------");
  return new Promise((resolve, reject) => {
    try {
      resolve(JSON.parse(fs.readFileSync(path).toString()));
    } catch (error) {
      console.log("Error reading Tokens from a file:" + path);
      resolve(undefined)
    }
  })
}


/**
 * @param {string} query The question to ask.
 */
function getAnswerOn(question) {
  console.log("inside getAnswerOn(question) function ------------------------");
  return new Promise((resolve) => {
    //https://millermedeiros.github.io/mdoc/examples/node_api/doc/readline.html
    const rl = readline.createInterface({
      input: process.stdin,
      output: process.stdout,
    });

    rl.question(question, (answer) => {
      console.log("Answer received succesfully!");
      rl.close();
      process.stdin.destroy();
      resolve(answer);
    });

  })
}



/**
 * Get and store new token after prompting for user authorization, and then
 * execute the given callback with the authorized OAuth2 client.
 * @param {OAuth2Client} oAuth2Client The OAuth2 client to get token for.
 * @param {string[]} scopes Scopes to get authorization for.
 * @param {string} tokenFilePath Path to a JSON file to store the tokens in.
 * @returns {OAuth2Client} terurns updated oAuth2Client
 */
function getNewTokensFromGoogleCLI(oAuth2Client, scopes, tokenFilePath) {
  console.log("inside getNewTokensFromGoogleCLI() function ------------------------");
  return new Promise((resolve, reject) => {

    const authUrl = oAuth2Client.generateAuthUrl({
      access_type: 'offline',
      scope: scopes,
    });

    console.log('Authorize this app by visiting this (Google login) url: ', authUrl);

    getAnswerOn("Enter the long code from that page here:").then(answer => {
      try {
        console.log("trying to get new token (before getToken) ------------------")
        oAuth2Client.getToken(answer, (err, tokens) => {
          if (!err) {
            // Now tokens contains an access_token and an optional refresh_token. Save them.
            oauth2Client.setCredentials(tokens);
            resolve(oauth2Client) //return updated oauth2Client <-----------------------------
            try {
              // Store the token to disk for later program executions
              fs.writeFileSync(tokenFilePath, JSON.stringify(tokens));
              console.log('Token stored to', tokenFilePath);
            } catch (error) {
              console.error("Error while storing tokens in a file", error);
              reject(new functions.https.HttpsError(error.code, error.message));
            }
          } else {
            console.error('Error in oAuth2Client.getToken() function', err);
            reject(new functions.https.HttpsError(err.code, err.message));
          }
        })
      } catch (error) {
        console.error('Error while trying to retrieve access token', error);
        reject(new functions.https.HttpsError(error.code, error.message));
      }
    })
  })
}


function authorize(key, scopes, tokenPath) {
  console.log("inside authorize() function ------------------------");
  return new Promise((resolve, reject) => {
    try {

      let REQ_SCOPES = scopes;
      if (Array.isArray(scopes)) {
        REQ_SCOPES = scopes.join(" "); //convert an array to the string  
      }

      /*
      * Create a new OAuth2 client with the configured keys.
      * https://github.com/googleapis/google-api-nodejs-client
      */
      const oauth2Client = new google.auth.OAuth2(
        key.client_id,
        key.client_secret,
        key.redirect_uris[0]
      );

      readAuth2TokensFromFile(tokenPath).then(tokens => {
        if (tokens) {
          oauth2Client.setCredentials(auth2tokensTokens);
          resolve(oauth2Client);
        } else {
          getNewTokensFromGoogleCLI(oauth2Client, REQ_SCOPES, tokenPath).then(updatedOAauth2Client => {
            resolve(updatedOAauth2Client)
          })
        }
      })
    } catch (error) {
      console.error('Error while getting a new oauth2Client from key: ', error);
      reject(new functions.https.HttpsError(error.code, error.message));
    }
  })
}

//Use: const { authorize } = require('./OAuth2Authorizer.js');
exports.authorize = authorize;

1 个答案:

答案 0 :(得分:1)

Oauth2工作应用程序的方式需要请求用户权限才能访问其数据。为此,我们向他们显示同意书。您的脚本告诉您

console.log('Authorize this app by visiting this (Google login) url: ', authUrl);
getAnswerOn("Enter the long code from that page here:").then(answer => {

在这里看到

  

通过访问以下URL(Google登录)授权此应用:https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&scope= ...

获取它为您提供的完整URL。将其放在网络浏览器中,表示同意访问,它将为您提供授权码。取回此代码,并将其放在等待它的应用程序中。

您的应用程序不会挂起,等待您响应其请求。