Google 身份验证挂起等待响应

Google auth hanging waiting for response

执行日志:

inside authorize() function ------------------------
inside readAuth2TokensFromFile() function ------------------------
Error reading Tokens from a file:./credentials/token.json inside getNewTokensFromGoogleCLI() function ------------------------
Authorize this app by visiting this (Google login) url: https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&scope=...
inside getAnswerOn(question) function ------------------------

...等待来自 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 
//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;

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

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

如图所示

Authorize this app by visiting this (Google login) url: https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&scope=...

充分利用它给你的URL。把它放在网络浏览器中同意访问,它会给你一个授权码。取回此代码并将其放置在等待它的应用程序中。

您的应用程序没有挂起,它正在等待您响应它的请求。