簡體   English   中英

為 Google 服務帳戶身份驗證正確創建 JWT 時遇到問題

[英]Having trouble correctly creating JWT for google service account auth

我正在嘗試在scriptr.io上創建一個腳本,該腳本創建一個JWT/JWS以發送到 google 的令牌端點,以便為我的服務帳戶獲取auth_token 我正在使用CryptoJS 庫來進行加密。 我能夠生成 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 將請求發送到令牌端點時,我得到以下響應

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

知道我哪里出錯了嗎? 有人可以幫我正確格式化 JWT 以便我可以獲得令牌嗎?

使用的函數是做散列,而不是數字簽名

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

不支持帶有 RSA 私鑰的數字簽名。 看一下CryptoJS的主存儲庫中的注釋

不活動

CryptoJS 是一個我在業余時間喜歡和工作的項目,但不幸的是,我的朝九晚五並沒有像以前那樣給我留下那么多的空閑時間。 我仍然想在未來繼續改進它,但我不能說那會是什么時候。 如果您發現 CryptoJS 不能滿足您的需求,那么我建議您嘗試 Forge。

我建議移動代碼以使用推薦的其他 Javascript 庫。 例如偽造支持 RSA 簽名( https://github.com/digitalbazaar/forge#rsa


Google OAuth2 服務器使用RS256 我提供了一個片段來使用 RSA 和 SHA256 將密鑰(我假設為 PEM 格式)轉換為偽造和簽名數據

Google OAuth 2.0 授權服務器支持的唯一簽名算法是使用 SHA-256 散列算法的 RSA。 這在 JWT 標頭的 alg 字段中表示為 RS256。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM