谷歌 API 服务帐户 "error" : "invalid_grant" , "error_description" : "Invalid JWT Signature."



我对谷歌 API 很陌生,但我已经花了 6 个小时来处理这个错误。因此,我想使用服务帐户访问我的Google云端硬盘文件。但我总是收到此错误:

{"error":"invalid_grant","error_description":"无效的 JWT 签名。"}

这是我在 NodeJs 中创建和发送 JWT 的方法:

const privateKeyFile = require("./user.json");
const base64url = require("base64url");
const jsonwebtoken = require("jsonwebtoken");
const querystring = require("querystring");
const request = require("request");
// HEADER
let header = { alg: "RS256", typ: "JWT" };
let encodedH = base64url(JSON.stringify(header));
// CLAIM SET
let exp = parseInt(Date.now() / 1000) + 60 * 20;
// issue time
let iat = parseInt(Date.now() / 1000);
let claimset = {
iss: "*********@*******.iam.gserviceaccount.com",
scope: "https://www.googleapis.com/auth/drive",
aud: "https://oauth2.googleapis.com/token",
exp: exp,
iat: iat,
};
let encodedCs = base64url(JSON.stringify(claimset));

// create signiture
let signitureBase = encodedH + "." + encodedCs;
jsonwebtoken.sign(
signitureBase,
privateKeyFile.private_key,
{
algorithm: "RS256",
header: header,
},
function (err, signature) {
request.post(
"https://oauth2.googleapis.com/token",
{
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: querystring.encode({
grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
assertion: signitureBase + "." + base64url(signature),
}),
},
function (error, response) {
console.log(error);
console.log(response);
}
);
}
);

提前感谢!

我相信你的目标如下。

  • 您希望使用 Node.js 从 Google 服务帐号中检索访问令牌。

为此,这个答案怎么样?

模式 1:

在此模式中,使用cryptorequest

示例脚本:

const privateKeyFile = require("./user.json");
const cryptor = require("crypto");
const request = require("request");
const scopes = ["https://www.googleapis.com/auth/drive"];
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: privateKeyFile.client_email,
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(privateKeyFile.private_key, "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);
}
);

结果:

运行脚本时,将检索以下结果。

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

模式 2:

在此模式中,使用googleapis

示例脚本:

const privateKeyFile = require("./user.json");
const { google } = require("googleapis");
let jwtClient = new google.auth.JWT(
privateKeyFile.client_email,
null,
privateKeyFile.private_key,
["https://www.googleapis.com/auth/drive"]
);
jwtClient.authorize((err) => {
if (err) console.log(err);
});
jwtClient.getRequestHeaders().then((auth) => {
console.log(auth);
});

结果:

运行脚本时,将检索以下结果。

{
"Authorization": "Bearer ###"
}

参考:

  • Googleapis for Node.js

相关内容

最新更新