【问题标题】:Authenticate REST request to Google APIs验证对 Google API 的 REST 请求
【发布时间】:2021-08-11 01:47:32
【问题描述】:

我在验证对 Google API 的 REST 请求时遇到问题。通常,Google 会为您提供客户端软件包。

现在,我正在使用文档翻译服务,该服务仍处于预览阶段,所以我无法使用该软件包。在验证 REST 请求时,文档确实令人困惑。当我使用一个包时,我给它一个带有这个模板的 JSON 凭证文件:

{
  "type": "xxx",
  "project_id": "xxx",
  "private_key_id": "xxx",
  "private_key": "xxx",
  "client_email": "xxx",
  "client_id": "xxx",
  "auth_uri": "xxx",
  "token_uri": "xxx",
  "auth_provider_x509_cert_url": "xxx",
  "client_x509_cert_url": "xxx"
}

我可以发送 REST 请求并仅使用其中的一些数据进行身份验证,就像我使用客户端软件包时一样吗?我在一些地方看到我应该使用这些数据生成一个令牌并使用一个令牌进行身份验证。我需要生成和使用令牌吗?如果是,如何在 NodeJS 中创建令牌?

【问题讨论】:

  • 虽然我不确定我是否能正确理解你的问题,但我提出了一个答案。你能确认一下吗?如果我误解了您的问题并且这不是您期望的方向,我深表歉意。
  • 我的回答是否向您展示了您想要的结果?你能告诉我吗?这对我学习也很有用。如果这可行,与您有相同问题的其他人也可以将您的问题作为可以解决的问题。如果您对我的回答有疑问,我深表歉意。到时候,可以问一下你现在的情况吗?我想学习解决你的问题。
  • 嘿田池。首先,感谢您花时间回答我的问题。是的,你正确理解了我的问题。主要的,我想找到一种无需创建令牌即可进行身份验证的方法。这种流动对我来说没有意义。我们在获取令牌时是在对自己进行身份验证,那么为什么我们不能直接使用获取令牌时使用的相同数据发送请求。我看到你是谷歌专家,所以也许你可以向我解释一下为什么这个流程是必要的?谢谢!
  • 另外,回答你关于我目前情况的问题。正如我在问题中所说,我正在使用文档翻译服务,该服务仍处于预览阶段。正因为如此,它仍然没有记录在相关的包文档中。在检查了所有相关文档后,我打开了包的源代码并开始调查。我发现在v3beta1 文件夹中有支持文档翻译的功能,即使没有关于它们的文档。所以,我只是用了那些功能,通过包实现了认证。
  • 我还注意到一个更有趣的问题。我打开了关于它的单独问题,所以如果你有时间也许你也可以检查一下?我还没有找到解决方案。这是问题:stackoverflow.com/q/67645265/14389830

标签: javascript node.js google-api google-api-nodejs-client


【解决方案1】:

我相信你目前的情况和你的目标如下。

  • 您拥有服务帐户的凭据文件。
  • 您想通过服务帐户使用 Google API。
  • 您希望使用 Node.js 实现此目的。但是,您不想使用googleapis for Node.js。您想在没有 googleapis for Node.js 的情况下使用此服务帐号。
  • 您的问题有以下 2 个问题。
    1. 我可以发送 REST 请求并仅使用其中一些数据进行身份验证,就像我使用客户端包时一样吗?
    2. 我需要生成和使用令牌吗?如果是,如何在 NodeJS 中创建令牌?

问题一的答案:

我认为是的。

问题2的答案:

我认为是的。为了使用服务帐户使用 Google API,需要使用服务帐户检索访问令牌。 Node.js 的不使用 googleapis 从服务帐户检索访问令牌的示例脚本如下。

示例脚本:

在这种情况下,使用了cryptorequest 两个库。并且,请设置privateKeyclientEmail。该脚本来自this post

const cryptor = require('crypto');
const request = require('request');

const privateKey = "-----BEGIN PRIVATE KEY-----\n###-----END PRIVATE KEY-----\n"; // private_key of JSON file retrieved by creating Service Account
const clientEmail = "###"; // client_email of JSON file retrieved by creating Service Account

const scopes = ["https://www.googleapis.com/auth/drive.readonly"]; // Sample scope

const url = "https://www.googleapis.com/oauth2/v4/token";
const header = {
  alg: "RS256",
  typ: "JWT",
};
const now = Math.floor(Date.now() / 1000);
const claim = {
  iss: clientEmail,
  scope: scopes.join(" "),
  aud: url,
  exp: (now + 3600).toString(),
  iat: now.toString(),
};

const signature = Buffer.from(JSON.stringify(header)).toString('base64') + "." + Buffer.from(JSON.stringify(claim)).toString('base64');

var sign = cryptor.createSign('RSA-SHA256');
sign.update(signature);
const jwt = signature + "." + sign.sign(privateKey, 'base64');

request({
  method: "post",
  url: url,
  body: JSON.stringify({
    assertion: jwt,
    grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
  }),
}, (err, res, body) => {
  if (err) {
    console.log(err);
    return;
  }
  console.log(body);
});
  • 在此示例中,使用https://www.googleapis.com/auth/drive.readonly 作为示例范围。关于这一点,请根据您的实际情况修改范围。

结果:

运行上述脚本时,将返回以下值。您可以使用此值的访问令牌,也可以使用此访问令牌使用 Google API。

{
  "access_token":"###",
  "expires_in":3599,
  "token_type":"Bearer"
}

注意:

  • 作为重要的一点,例如,当您使用此脚本使用 Google Drive API 时,服务帐户的 Drive 与您的 Google Drive 不同。请注意这一点。当您想通过服务帐号使用云端硬盘上的文件时,需要与服务帐号的邮箱共享文件。

参考资料:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-31
    • 2020-03-14
    相关资源
    最近更新 更多