Nodejs发布请求以获取服务帐户的oauth2令牌
我试图使用nodejs为我的服务帐户获取oauth2令牌。我在下面这里找到的文档:Nodejs发布请求以获取服务帐户的oauth2令牌
https://developers.google.com/identity/protocols/OAuth2ServiceAccount#makingrequest
虽然还没有一个节点的例子,我已经看过了HTTP/REST文件,以获得它做了一个请求时,需要一个粗略的想法令牌。然而,我回来的回应是:
无效的JWT签名。
作为计算签名的一般概述,您可以使用base64url编码的值作为标题和声明,使用sha256和来自Google开发者控制台的私钥对其进行哈希处理,然后使用base64url对该值进行编码。
所以我的头是:
var header = {"alg":"RS256","typ":"JWT"}
var encodedHeader = base64url(new Buffer(header).toString('utf8'));
上面甚至文档列出这个值是什么base64url后对其进行编码:
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9
当我输出我encodedHeader值:
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9
哦,它匹配很好。所以不应该有其他值的64burl编码问题。接下来是索赔:
var claim ={"aud":"https://www.googleapis.com/oauth2/v4/token","scope":"https://www.googleapis.com/auth/gmail.send","iss":"*****censoredvalue*****gserviceaccount.com","exp":1505399833,"iat":1505396233}
它经历了相同的过程,并进行了编码(出于安全原因无法显示)。
var encodedClaim = base64url(new Buffer(claim).toString('utf8'));
就目前我使用的是第三方网站来计算测试目的的签名,但输入的是encodedHeader.encodedClaim +私有密钥(值为:----- BEGIN PRIVATE KEY .... )并使用SHA256。然后我会把这个输出和b64url编码。
我现在有一个JWT是encodedHeader.encodedClaim.encodedSignature
var encoded_jwt = encodedHeader + '.' + encodedClaim + '.' + encodedSignature;
我要让令牌端点的要求有以下:
// Set the headers
var headers = {
'HTTP-Version': 'HTTP/1.1',
'Content-Type': 'application/x-www-form-urlencoded'
}
var bodyOptions = { 'grant_type': "urn:ietf:params:oauth:grant-type:jwt-bearer", assertion: encoded_jwt }
// Configure the request
var options = {
url: 'https://www.googleapis.com/oauth2/v4/token',
method: 'POST',
headers: headers,
form: bodyOptions,
json: true
}
// Start the request
request(options, function (error, response, body) {
if (!error && response.statusCode == 200) {
// Print out the response body
console.log(body)
}
else{
context.log(error);
context.log(response);
}
});
这是从哪里获得一个错误的回复说我有一个无效的签名。
任何有关为什么它是无效签名的想法。我也尝试了几个签名生成网站,以确保它不是一个特定的网站,但它始终是相同的错误。
为了计算JWS,您可以使用crypto module类似如下:
const privateKey = fs.readFileSync('private.pem', 'utf-8');
const signer = crypto.createSign('sha256');
signer.update(data);
const signature = signer.sign(privateKey, 'base64');
其中data
是encodedHeader + '.' + encodedClaim
从google-oauth-library测试用例采取一个完整的例子:
"use strict";
const crypto = require('crypto');
const fs = require('fs');
const publicKey = fs.readFileSync('public.pem', 'utf-8');
const privateKey = fs.readFileSync('private.pem', 'utf-8');
const maxLifetimeSecs = 86400;
const now = new Date().getTime()/1000;
const expiry = now + (maxLifetimeSecs/2);
const idToken = '{' +
'"iss":"testissuer",' +
'"aud":"testaudience",' +
'"azp":"testauthorisedparty",' +
'"email_verified":"true",' +
'"id":"123456789",' +
'"sub":"123456789",' +
'"email":"[email protected]",' +
'"iat":' + now + ',' +
'"exp":' + expiry + '}';
const envelope = '{' +
'"kid":"keyid",' +
'"alg":"RS256"' +
'}';
let data = new Buffer(envelope).toString('base64') + '.' +
new Buffer(idToken).toString('base64');
const signer = crypto.createSign('sha256');
signer.update(data);
const signature = signer.sign(privateKey, 'base64');
data += '.' + signature;
console.log(data);