【问题标题】:Google Api Service Account "error":"invalid_grant","error_description":"Invalid JWT Signature."Google Api 服务帐户 "error":"invalid_grant","error_description":"无效的 JWT 签名。"
【发布时间】:2020-09-01 18:15:38
【问题描述】:

我对 google api 很陌生,但我已经花了 6 个小时来处理这个错误。所以我想使用服务帐户访问我的谷歌驱动器文件。但我总是得到这个错误:

{"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-api jwt


    【解决方案1】:

    我相信你的目标如下。

    • 您想使用 Node.js 从 Google 服务帐户检索访问令牌。

    对于这个,这个答案怎么样?

    模式一:

    在此模式中,使用了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 ###"
    }
    

    参考:

    【讨论】:

    • 完美!非常感谢! :)
    • @Andor 感谢您的回复。很高兴您的问题得到解决。
    猜你喜欢
    • 2018-10-04
    • 2021-10-03
    • 1970-01-01
    • 2018-08-03
    • 1970-01-01
    • 2014-09-22
    • 2018-06-14
    • 2021-07-26
    • 2021-12-06
    相关资源
    最近更新 更多