简体   繁体   English

Google Api 服务帐户“错误”:“invalid_grant”,“error_description”:“JWT 签名无效。”

[英]Google Api Service Account "error":"invalid_grant","error_description":"Invalid JWT Signature."

I am pretty new with google api, but I already spent 6 hours with this error.我对谷歌 api 很陌生,但我已经花了 6 个小时解决这个错误。 So I want to access my google drive files with a service account.所以我想使用服务帐户访问我的谷歌驱动器文件。 But I always get this error:但我总是得到这个错误:

{"error":"invalid_grant","error_description":"Invalid JWT Signature."} {“error”:“invalid_grant”,“error_description”:“JWT 签名无效。”}

This is the method I create and send the JWT in NodeJs:这是我在 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);
      }
    );
  }
);

Thanks in advance!提前致谢!

I believe your goal as follows.我相信你的目标如下。

  • You want to retrieve the access token from the Google service account using Node.js.您想要使用 Node.js 从 Google 服务帐户检索访问令牌。

For this, how about this answer?为此,这个答案怎么样?

Pattern 1:模式 1:

In this pattern, crypto and request are used.在此模式中,使用了cryptorequest

Sample script:示例脚本:

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);
  }
);

Result:结果:

When you run the script, the following result is retrieved.运行脚本时,将检索到以下结果。

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

Pattern 2:模式 2:

In this pattern, googleapis is used.在此模式中,使用了googleapis

Sample script:示例脚本:

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);
});

Result:结果:

When you run the script, the following result is retrieved.运行脚本时,将检索到以下结果。

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

Reference:参考:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM