[英]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.