如何将访问代码从 gmail api 传递给 Heroku 中的节点工作者

Posted

技术标签:

【中文标题】如何将访问代码从 gmail api 传递给 Heroku 中的节点工作者【英文标题】:How to pass an access code from gmail api to a node worker in Heroku 【发布时间】:2021-05-29 15:07:23 【问题描述】:

应用程序

我用 discord.js 编写了一个不和谐的机器人作为一个简单的 node.js 应用程序,而不是一个网络服务器。我已将 gmail api 与凭据文件集成,以验证自己以访问电子邮件。这在本地主机上的开发中完美运行。

问题

当我启动应用程序时,谷歌会提示我转到外部 url 并授权应用程序。在那里我得到一个代码,并在我的应用程序的控制台中提示我输入该代码。当我在我的机器上运行它时很好,但是在 heroku 上运行时,我似乎无法将代码传递回应用程序。

我的(失败的)解决方案

到目前为止我已经尝试过: 使用 heroku cli 将代码传回 使用heroku界面中的集成控制台(发电机)将代码传回 在我真的绝望的时候一味的复制到日志里

在所有尝试中,令牌都没有保存在我部署的应用程序中,所以提示一次又一次。

代码

有问题的代码传递回代码是这样的:
function getNewToken(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);
    );
  );

我能做些什么来解决这个问题?也许只是通过console 记录令牌并手动保存?还是有另一种我看不到的更简单的身份验证方法?

【问题讨论】:

【参考方案1】:

解决方案

我的解决方案是将 readline 函数交换为来自 discord bot 的操作并手动触发身份验证:
const  manualAuthorization, sendToken  = require("../authorize-google");

module.exports = 
  name: "authorize-google",
  admin: true,
  execute: async (_message, [code]) => 
    try 
      if (!code) 
        await manualAuthorization();
       else 
        await sendToken(code);
      
     catch (error) 
      throw new Error(error.message);
    
  ,
;

第一个命令触发身份验证,第二个命令将代码发送给机器人:

function manualAuthorization() 
  OWNER = client.users.cache.get("someID");

  // Load client secrets from a local file.
  Fs.readFile("google-credentials.json", (err, content) => 
    if (err) 
      return console.log("Error loading client secret file:", err);
    
    // Authorize a client with credentials, then call the Gmail API.
    authorize(JSON.parse(content));
  );


/**
 * Create an OAuth2 client with the given credentials, and then execute the
 * given callback function.
 * @param Object credentials The authorization client credentials.
 */
function authorize(credentials) 
  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 getNewToken(oAuth2Client);
    
    oAuth2Client.setCredentials(JSON.parse(token));
    OWNER.send("Successfully authorized");
  );


/**
 * 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.
 */
function getNewToken(oAuth2Client) 
  const authUrl = oAuth2Client.generateAuthUrl(
    access_type: "offline",
    scope: SCOPES,
  );

  client.oAuth2Client = oAuth2Client;

  OWNER.send(`Authorize this app by visiting this url: $authUrl`);


function sendToken(code) 
  client.oAuth2Client.getToken(code, (err, token) => 
    if (err) 
      return console.error("Error retrieving access token", err);
    

    client.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);
    );

    OWNER.send("Successfully authorized");
  );

【讨论】:

以上是关于如何将访问代码从 gmail api 传递给 Heroku 中的节点工作者的主要内容,如果未能解决你的问题,请参考以下文章

在 GMAIL API Get Calls 中传递变量值

Google Api,如何将访问令牌传递给API调用

如何从我的 Android 应用程序访问新的 Gmail API?

如何将用户输入从节点服务器传递到外部 api 调用?

何时将刷新令牌传递给 API

如何将标头动态传递给 angularjs 的 $resource