当前位置: 首页 > 知识库问答 >
问题:

在首次自动使用之外维护谷歌客户端API refresh_token

汝天宇
2023-03-14

有人曾经为google api维护过OAuth2 refresh_token,我可以和你比较一下代码吗?文档说,如果我用access _ type:“offline”创建access_token,客户端api将在到期前自动使用refresh_token,但在我的情况下,这种情况只发生一次,此时refresh_token从更新的token对象中消失。我的代码就这么简单:

async function google(request)
{let [{google},keys]=await Promise.all(
[import("./node_modules/googleapis/build/src/index.js")
,import("./keys.json").then(json=>json.default)
]);
 let {client,secret,token}=keys;
 let authority=new google.auth.OAuth2(client,secret,request.url);
 authority.on('tokens',token=>save("keys.json",{...keys,token}).then(console.log));
 if(!token)
 if(!request.query.code)
 return authority.generateAuthUrl({scope,access_type:"offline",prompt:"consent"});
 else return new Promise(resolve=>
 authority.getToken(request.query.code,resolve)).then(fail=>fail||"new access_token");
 authority.setCredentials(token);
 google=google.sheets({version:"v4",auth:authority});
 return new Promise(resolve=>
 google.spreadsheets.values.get(sheet,resolve)).then(fail=>fail||"valid token");
 // first return value: [consent url redirecting to the same endpoint]
 // after using the url: "new access_token"
 // during the next 2 hours: "valid token" ("refresh_token" gone missing from keys.json in the second hour)
 // after 2 hours: "Error: missing required parameter: refresh_token"
}

可能是因为我在每个请求上动态地重新验证API?我也每次都设置凭据,因此与拥有静态API没有任何区别

共有2个答案

康元凯
2023-03-14

我对DalmTo的回答的评论被证明是正确的:access_token的refresh_token是静态的,所以问题是当保存新令牌时,必须保留refresh_token。在文档中提到这一点可能也是有用的,除非是这样,我只是错过了这个细节。

屈宏爽
2023-03-14

这是我手头上最好的例子,它使用不同的API,但应该给你一个想法。

库不为您保存或加载。但是,它确实支持将刷新令牌加载到其中。因此,只要您将它保存在某个位置,然后在正确的时间加载它,它就会工作。

检查我如何使用TOKEN_PATH这是存储令牌的路径。当代码首次运行时,系统将尝试读取该文件并加载存储在其中的任何令牌。

请注意,刷新令牌只会在第一次使用时返回给您,如果您需要它,您需要保存它。而不是意外地用null覆盖它。

“自述文件”中有很多关于如何设置的信息。Google api node.js客户端

const fs = require('fs');
const readline = require('readline');
const {google} = require('googleapis');
const dotenv = require('dotenv');
dotenv.config();
const CRED_FILE_PATH = process.env.API_CREDS;
console.log(`Your cred path is ${CRED_FILE_PATH}`); // ../creds.json
const VIEW_ID = process.env.VIEW_ID;
console.log(`Your view id is ${VIEW_ID}`);

// If modifying these scopes, delete token.json.
const SCOPES = ['https://www.googleapis.com/auth/analytics.readonly'];
// The file token.json stores the user's access and refresh tokens, and is
// created automatically when the authorization flow completes for the first
// time.
const TOKEN_PATH = 'token.json';

// Load client secrets from a local file.
fs.readFile(CRED_FILE_PATH, (err, content) => {
    if (err) return console.log('Error loading client secret file:', err);
    // Authorize a client with credentials, then call the Google Drive API.
    authorize(JSON.parse(content), getUserReport);
});

/**
 * Create an OAuth2 client with the given credentials, and then execute the
 * given callback function.
 * @param {Object} credentials The authorization client credentials.
 * @param {function} callback The callback to call with the authorized client.
 */
function authorize(credentials, callback) {
    const {client_secret, client_id, redirect_uris} = credentials.installed;
    const oAuth2Client = new google.auth.OAuth2(
        client_id, client_secret, redirect_uris[0]);

    // Check if we have previously stored a token.
    fs.readFile(TOKEN_PATH, (err, token) => {
        if (err) return getAccessToken(oAuth2Client, callback);
        oAuth2Client.setCredentials(JSON.parse(token));
        callback(oAuth2Client);
    });
}

/**
 * Get and store new token after prompting for user authorization, and then
 * execute the given callback with the authorized OAuth2 client.
 * @param {google.auth.OAuth2} oAuth2Client The OAuth2 client to get token for.
 * @param {getEventsCallback} callback The callback for the authorized client.
 */
function getAccessToken(oAuth2Client, callback) {
    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);
            // Store the token to disk for later program executions
            fs.writeFile(TOKEN_PATH, JSON.stringify(token), (err) => {
                if (err) return console.error(err);
                console.log('Token stored to', TOKEN_PATH);
            });
            callback(oAuth2Client);
        });
    });
}
 类似资料:
  • 我有一个谷歌云,我想推我的图像。 我的图片是Hello-world项目与节点快递谷歌云客户端libray 你可以在我的github上找到它 https://github.com/innostarterkit/language 当我试着推的时候,我有这个错误 推送是指存储库[eu.gcr.io/innovation xxx/hello]a419c4413fb0:推送[================

  • 我正在编写一个类,用于创建对BigQuery和Google云存储的授权。 在过去,我曾使用,但已被弃用。我试图使用,但我发现它只允许我使用,而我需要。 我知道可以从转换为,但我不知道如何将它们转换成相反的方向(转换为)。例如,我像这样创建连接: 有人能给我指明如何实现这一目标的方向吗? 谢谢!

  • 我正在尝试使用我的应用程序中的google帐户登录用户。当用户第一次在我的应用程序中使用google帐户登录时,我遇到了一个问题。它显示了以下错误:传递给Illumb\Auth\Guard::login()的参数1必须实现interface Illumb\Auth\UserInterface,在我的控制器中为空我有以下信息: 我知道问题出在Auth::login($user);因为插入与Auth:

  • 我试图访问我的用户的google drive内容。我可以使用带有正确参数的google drive用户许可url在我的域名上兑换代码:https://accounts.google.com/o/oauth2/v2/auth?响应类型=代码 我正在尝试向https://www.googleapis.com/oauth2/v4/tokenendpoint执行角$超文本传输协议请求。请求如下所示: 然而

  • 我将appengine gcs客户端添加到我的Google appengine标准项目中: (此页上的说明如下:https://cloud.google.com/appengine/docs/standard/java/googlecloudstorageclient/setting-up-cloud-storage) 编译项目会引发以下错误(几天前没有问题): [错误]无法在项目myprojec

  • 当您使用Google Drive Web客户端时,您可以第一次选择要连接的Google帐户。完成后续调用后,跳过您可以选择帐户的步骤——您不必再次授权。有没有办法在不实际退出Google帐户的情况下再次触发帐户选择? 我正在使用文件选择器API,参见https://developers.google.com/picker/docs/