javascript - 为 Google 服务帐户身份验证正确创建 JWT 时遇到问题

标签 javascript google-sheets google-api jwt google-authentication

我正在尝试在scriptr.io上创建一个脚本创建 JWT/JWS发送到 google 的 token 端点,以便为我的服务帐户获取 auth_token。我正在使用CryptoJS library为了进行加密。我能够生成 JWT 的所有 3 个部分,但这样做时我做错了一些事情。我相信它与字符串三个部分中的最后一个(即签名部分)有关,但我可能是错的。

var cryptoJs = {};
cryptoJs['SHA256'] = require('CryptoJS/rollups/sha256.js').CryptoJS.SHA256

var pHeader = {"alg":"RS256","typ":"JWT"}
var sHeader = JSON.stringify(pHeader);
var encodedHeader = Base64EncodeUrl(btoa(sHeader));
console.log("encodedHeader: " + encodedHeader);

var now = new Date();
var oneHourExpiration = ((now.getTime()-now.getMilliseconds())/1000)+3000;//3000, not 3600 which is 1 hour

var pClaim = {};
pClaim.iss = "-------@---iam.gserviceaccount.com";
pClaim.scope = "https://www.googleapis.com/auth/spreadsheets";
pClaim.aud = "https://www.googleapis.com/oauth2/v3/token";
pClaim.exp = oneHourExpiration;
pClaim.iat = Math.floor(Date.now()/1000);
console.log("exp: " + pClaim.exp);
console.log("iat: " + pClaim.iat);

var sClaim = JSON.stringify(pClaim);
var encodedClaim = Base64EncodeUrl(btoa(sClaim));
console.log("encodedClaim: " + encodedClaim);

var byteArray = encodedHeader + "." + encodedClaim;
console.log("byteArray: " + byteArray);

var secret = "-----BEGIN PRIVATE KEY-----\n.....MIIE.....=\n-----END PRIVATE KEY-----\n";
var signature = cryptoJs.SHA256(byteArray, secret);
var encodedSignature = Base64EncodeUrl(btoa(signature));
console.log("Encoded Signature: " + encodedSignature);

var sJWS = byteArray + "." + encodedSignature;
console.log("JWT: " + sJWS);

function Base64EncodeUrl(str){
    return str.replace(/\+/g, '-').replace(/\//g, '_').replace(/\=+$/, '');
}

var http = require("http");
var requestObject = {
  "url": "https://www.googleapis.com/oauth2/v3/token",
  "method": "POST",
  "headers": {"Content-Type":"application/x-www-form-urlencoded"},
  "params": {"grant_type":"urn:ietf:params:oauth:grant-type:jwt-bearer","assertion":sJWS}
}


var response = http.request(requestObject);
var responseBodyStr = response.body;
console.log(responseBodyStr);
var token = JSON.parse(responseBodyStr.access_token);
console.log(token);

当我使用 JWT 将请求发送到 token 端点时,我收到以下响应

{  
    "error": "invalid_grant",
    "error_description": "Invalid JWT Signature."
 }

知道我哪里出错了吗?有人可以帮助我正确格式化 JWT 以便我可以获得 token 吗?

最佳答案

使用的函数是进行哈希计算,而不是数字签名

var signature = cryptoJs.SHA256(byteArray, secret);

不支持使用 RSA 私钥进行数字签名。看看CryptoJS主存储库中的评论

Inactivity

CryptoJS is a project that I enjoy and work on in my spare time, but unfortunately my 9-to-5 hasn't left me with as much free time as it used to. I'd still like to continue improving it in the future, but I can't say when that will be. If you find that CryptoJS doesn't meet your needs, then I'd recommend you try Forge.

我建议移动代码以使用推荐的其他 Javascript 库。例如 forge 支持 RSA 签名 ( https://github.com/digitalbazaar/forge#rsa )

<小时/>

Google OAuth2 服务器使用RS256。我提供了一个片段来转换 key (我假设 PEM 格式),以使用 RSA 和 SHA256 来伪造和签名数据

The only signing algorithm supported by the Google OAuth 2.0 Authorization Server is RSA using SHA-256 hashing algorithm. This is expressed as RS256 in the alg field in the JWT header.

// convert a PEM-formatted private key to a Forge private key
var privateKey = forge.pki.privateKeyFromPem(pem);

// sign data with a private key and output DigestInfo DER-encoded bytes (defaults to RSASSA PKCS#1 v1.5)
var md = forge.md.sha256.create();
md.update(byteArray, 'utf8');
var signature = privateKey.sign(md);

//convert signature to base64
var encodedSignature = Base64EncodeUrl(btoa(signature));

关于javascript - 为 Google 服务帐户身份验证正确创建 JWT 时遇到问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42015178/

相关文章:

javascript - Array.prototype.forEach.call 给出 TypeError : Illegal invocation

javascript - 了解如何使用回调

php - 使用 Zend Gdata 将数百行插入到 Google 电子表格中?

c# - 将 google 凭据用于生产应用程序的最佳方式是什么?

google-api - 使用 .net 的服务器端应用程序的 Google 登录

javascript - 使用 casperJS 测试 jQuery Geocomplete 插件(自动完成)

javascript - 对于 IE 中的每个 JavaScript 支持?

javascript - 在表单提交时触发 Google 电子表格功能时遇到问题

c# - 如何使用 C# 和 Sheet Api 访问和插入数据到 Google Spread Sheet?

javascript - document.getElementById 不适用于动态 div