如何使 Google oAuth2Client 对象可重用 Node.js 应用程序范围?

How to make the Google oAuth2Client object reusable Node.js app-wide?

我正在构建一个 Node.js CLI,它执行 Google Drive API 和 Docs API 函数中预定义的调用。 但是因为每个 API 调用都必须被授权,我创建了一个单独的文件和函数来读取凭据,并且应该 return 授权的 oAuth2Client 对象被导出并在它所在的任何函数中重用需要作为参数传递。 这个想法是 readCredentials() 函数调用将调用 authorize() 函数,如果 token.json 存在,该函数应该 return oAuth2Client 对象。否则它将提示用户使用 getAccessToken() 函数进行身份验证。
整个逻辑实际上只是从 quickstart example in the Google Drive API docs 稍作修改,但旨在可在应用程序的任何功能中重复使用,而不仅仅是在当前文件中。
但是由于某种原因,当我尝试调用凭据并将其存储在变量中,然后使用它们在我的 index.js.
有人知道出了什么问题吗?

authorize.js

const fs = require("fs");
const readline = require("readline");
const { google } = require("googleapis");

const SCOPES = ["https://www.googleapis.com/auth/drive.file"];

const TOKEN_PATH = "token.json";

const readCredentials = () => {
  fs.readFile("credentials.json", (err, content) => {
    if (err) return console.log("Error loading client secret file:", err);
    authorize(JSON.parse(content));
  });
};

const authorize = (credentials) => {
  const { client_secret, client_id, redirect_uris } = credentials.installed;
  const oAuth2Client = new google.auth.OAuth2(
    client_id,
    client_secret,
    redirect_uris[0]
  );

  fs.readFile(TOKEN_PATH, (err, token) => {
    if (err) return getAccessToken(oAuth2Client);
    oAuth2Client.setCredentials(JSON.parse(token));
  });

  return oAuth2Client;
};

const getAccessToken = (oAuth2Client) => {
  const authUrl = oAuth2Client.generateAuthUrl({
    access_type: "offline",
    scope: SCOPES,
  });
  console.log("Authorize this app by visiting this url:", authUrl);
  const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
  });
  rl.question("Enter the code from that page here: ", (code) => {
    rl.close();
    oAuth2Client.getToken(code, (err, token) => {
      if (err) return console.error("Error retrieving access token", err);
      oAuth2Client.setCredentials(token);

      fs.writeFile(TOKEN_PATH, JSON.stringify(token), (err) => {
        if (err) return console.error(err);
        console.log("Token stored to", TOKEN_PATH);
      });

      return oAuth2Client;
    });
  });
};

module.exports = { readCredentials };

index.js

const authorize = require("./authorize");
const drive = require("./drive");
...
let credentials = authorize.readCredentials();

drive.createFolder(credentials);
...

对于 Node.js,您可以从使用 passport.js 开始。它将用户信息存储在一个会话中,可以用req.user访问。要使用 API,您需要用户的 access_token,您可以通过 refresh_token 获得。这是来自 passport.js 网站的基本示例。

var GoogleStrategy = require( 'passport-google-oauth2' ).Strategy;

passport.use(new GoogleStrategy({
    clientID:     GOOGLE_CLIENT_ID,
    clientSecret: GOOGLE_CLIENT_SECRET,
    callbackURL: "http://yourdomain:3000/auth/google/callback",
    passReqToCallback   : true
  },
  function(request, accessToken, refreshToken, profile, done) {
    User.findOrCreate({ googleId: profile.id }, function (err, user) {
      return done(err, user);
    });
  }
));


app.get('/auth/google',
  passport.authenticate('google', { scope:
      [ 'email', 'profile' ] }
));

app.get( '/auth/google/callback',
    passport.authenticate( 'google', {
        successRedirect: '/auth/google/success',
        failureRedirect: '/auth/google/failure'
}));

我建议也将 refresh_token 添加到数据库中,这样您就可以随时获得 access_token。在上面的示例中,它使用 Mongo 数据库。