终于搞定了!使用 kjur 的 jsjws 纯 JavaScript 实现 JWT。我使用this demo 作为生成JWT 来请求令牌的基础。以下是步骤
在 Google Developers 控制台中,我创建了一个服务帐户。以下是相关说明
在 Google API 控制台中,我将服务帐户添加到凭据中。然后我生成了一个新的 JSON 密钥。这给了我纯文本格式的私钥。
然后我按照 google 的这些说明使用 HTTP/REST 进行授权 API 调用。
这是必需的标头信息。
var pHeader = {"alg":"RS256","typ":"JWT"}
var sHeader = JSON.stringify(pHeader);
声明集是这样的。 (这是使用上述 KJUR JWT 库提供的语法。)
var pClaim = {};
pClaim.aud = "https://www.googleapis.com/oauth2/v3/token";
pClaim.scope = "https://www.googleapis.com/auth/analytics.readonly";
pClaim.iss = "<serviceAccountEmail@developer.gserviceaccount.com";
pClaim.exp = KJUR.jws.IntDate.get("now + 1hour");
pClaim.iat = KJUR.jws.IntDate.get("now");
var sClaim = JSON.stringify(pClaim);
有争议的一点是将我的私钥放入客户端代码中。对于这种用法,它并没有那么糟糕(我不认为。)首先,该站点位于我们公司的防火墙后面,那么谁来“破解”它?其次,即使有人得到它,服务帐户的唯一授权是查看我们的分析数据——我的仪表板的目的是任何访问该页面的人都可以查看我们的分析数据。这里就不贴私钥了,基本就这样吧。
var key = "-----BEGIN PRIVATE KEY-----\nMIIC....\n-----END PRIVATE KEY-----\n";`enter code here`
然后用
生成一个签名的JWT
var sJWS = KJUR.jws.JWS.sign(null, sHeader, sClaim, key);
之后我使用 XMLHttpRequest 调用 google API。我尝试将 FormData 与请求一起使用,但这没有用。所以老(呃)学校
var XHR = new XMLHttpRequest();
var urlEncodedData = "";
var urlEncodedDataPairs = [];
urlEncodedDataPairs.push(encodeURIComponent("grant_type") + '=' + encodeURIComponent("urn:ietf:params:oauth:grant-type:jwt-bearer"));
urlEncodedDataPairs.push(encodeURIComponent("assertion") + '=' + encodeURIComponent(sJWS));
urlEncodedData = urlEncodedDataPairs.join('&').replace(/%20/g, '+');
// We define what will happen if the data are successfully sent
XHR.addEventListener('load', function(event) {
var response = JSON.parse(XHR.responseText);
token = response["access_token"]
});
// We define what will happen in case of error
XHR.addEventListener('error', function(event) {
console.log('Oops! Something went wrong.');
});
XHR.open('POST', 'https://www.googleapis.com/oauth2/v3/token');
XHR.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
XHR.send(urlEncodedData)
之后我有了访问令牌,我可以关注these tutorials 使用嵌入 API,但像这样授权:
gapi.analytics.auth.authorize({
serverAuth: {
access_token: token
}
});
不要忘记您必须授予服务帐户查看内容的权限,就像任何其他用户一样。当然,如果服务帐户被授权执行只读以外的任何操作,那将是一个非常糟糕的主意。
我可能还会遇到关于时间和令牌过期的问题,但到目前为止一切都很好。