javascript - 如何使 Google oAuth2Client 对象在 Node.js 应用程序范围内可重用?
问题描述
我正在构建一个 Node.js CLI,它执行在函数中预定义的 Google Drive API 和 Docs API 调用。但是因为每个 API 调用都必须经过授权,所以我创建了一个单独的文件和函数来读取凭据,并且应该返回oAuth2Client
要导出的授权对象并在需要作为参数传递的任何函数中重用。这个想法是一个readCredentials()
函数调用将调用该函数,如果有一个存在authorize()
,它应该返回对象。否则它将提示用户使用该功能进行身份验证。
整个逻辑实际上只是从Google Drive API 文档中的快速入门示例略微修改oAuth2Client
token.json
getAccessToken()
,但旨在可在应用程序的任何功能中重用,而不仅仅是在当前文件中。
但由于某种原因GaxiosError: Login Required
,当我尝试调用凭据并将其存储在变量中时,我会在控制台中返回,然后使用它们在我的index.js
.
有人知道出了什么问题吗?
授权.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 数据库。
推荐阅读
- r - 在R中获取组中的下一个日期
- google-sheets - 使用命令行将数据从 BigQuery 加载到 Google 表格中
- php - 关联数组键在传递给 SoapClient 时成为 XML 中的参数
- python - 如何使覆盖的 QGraphicsTextItem 可编辑和可移动?
- sql - 根据一列/SQL Oracle 中的值创建时间间隔
- excel - VBA - 您不能在此处粘贴,因为复制区域和粘贴区域的大小不同
- amazon-web-services - 从媒体转换作业/服务设置 aws s3 存储类?
- bash - 在第一行写#!/bin/bash -x,但在执行过程中没有得到任何信息
- react-native - 使用 React Native(链接)在 Instagram 上发布多张照片
- angular - 如何在RouterModule中导入有条件的模块(loadChildren)?