![](/img/trans.png)
[英]How to get access token for Google APIs Data without User Consent using Service Account from Javascript
[英]How to obtain Google service account access token javascript
我正在嘗試為我的網站設置一個分析儀表板,供我的領導查看網站使用情況。 我不希望他們必須擁有谷歌帳戶或單獨添加他們才能查看結果。
我已經設置了一個服務帳戶和 OAuth2 訪問權限。 我找到的所有教程都顯示如下代碼:
gapi.analytics.auth.authorize({
clientid: 'Service account client ID',
serverAuth: {
access_token: 'XXXXXXXXXXXXXXXXX'
}
所有的文檔都在談論“......一旦你收到你的訪問令牌......”但他們實際上沒有說如何獲得它! 我看到證書指紋,公鑰指紋。 我還看到了如何生成 JSON 和 P12 密鑰。 我不知道如何生成訪問令牌。
有人可以解釋如何做到這一點嗎?
我找到了這個。 它解釋了我需要密鑰文件並且這是一個壞主意,但沒有說明如何實際操作。
我也發現了這個。 但我對 Node.js 一無所知,我希望這只是一種可能的途徑?
終於讓它工作了! 使用 kjur 的 jsjws 純 JavaScript 實現 JWT。 我使用這個演示作為生成 JWT 來請求令牌的基礎。 以下是步驟
在 Google Developers 控制台中,我創建了一個服務帳戶。 以下是相關說明
在 Google API 控制台中,我將服務帳戶添加到憑據中。 然后我生成了一個新的 JSON 密鑰。 這以純文本格式為我提供了我的私鑰。
然后我按照谷歌的這些說明使用 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 來調用谷歌 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)
之后我有了我的訪問令牌,我可以按照這些使用嵌入 API 的教程進行操作,但授權如下:
gapi.analytics.auth.authorize({
serverAuth: {
access_token: token
}
});
不要忘記,您必須授予服務帳戶查看內容的權限,就像任何其他用戶一樣。 當然,如果服務帳戶被授權做只讀以外的任何事情,那將是一個非常糟糕的主意。
我可能會遇到與時間和令牌到期有關的問題,但到目前為止一切順利。
您可以使用 Node.js 的官方(和 alpha)Google API 來生成令牌。 如果您有服務帳戶,這會很有幫助。
在服務器上:
npm install -S googleapis
ES6:
import google from 'googleapis'
import googleServiceAccountKey from '/path/to/private/google-service-account-private-key.json' // see docs on how to generate a service account
const googleJWTClient = new google.Auth.JWT(
googleServiceAccountKey.client_email,
null,
googleServiceAccountKey.private_key,
['https://www.googleapis.com/auth/analytics.readonly'], // You may need to specify scopes other than analytics
null,
)
googleJWTClient.authorize((error, access_token) => {
if (error) {
return console.error("Couldn't get access token", e)
}
// ... access_token ready to use to fetch data and return to client
// even serve access_token back to client for use in `gapi.analytics.auth.authorize`
})
現在,服務帳戶身份驗證有一個getAccessToken
方法可以為我們做到這一點。
const {google} = require('googleapis');
const main = async function() {
const auth = new google.auth.GoogleAuth({
keyFile: __dirname + '/service-account-key.json',
scopes: [ 'https://www.googleapis.com/auth/cloud-platform']
});
const accessToken = await auth.getAccessToken()
console.log(JSON.stringify(auth, null, 4))
console.log(JSON.stringify(accessToken, null, 4));
}
main().then().catch(err => console.log(err));
我在尋找類似的東西時遇到了這個問題,並認為我會分享一個我最終得到的 node.js 解決方案。 本質上,我將一個 google 服務帳戶保存到 sa.json 文件中,然后用它來簽署我發送給 gcp 的 jwt。
const jwt = require("jsonwebtoken");
const sa = require("./sa.json");
const fetch = require("isomorphic-fetch");
const authUrl = "https://www.googleapis.com/oauth2/v4/token";
const scope = "https://www.googleapis.com/auth/cloud-platform";
const getSignedJwt = () => {
const token = {
iss: sa.client_email,
iat: parseInt(Date.now() / 1000),
exp: parseInt(Date.now() / 1000) + 60 * 60, // 60 minutes
aud: authUrl,
scope,
};
return jwt.sign(token, sa.private_key, { algorithm: "RS256" });
};
const getGoogleAccessToken = async () => {
const signedJwt = getSignedJwt();
const body = new URLSearchParams();
body.append("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer");
body.append("assertion", signedJwt);
const response = await fetch(authUrl, {
method: "post",
headers: {
Authorization: `Bearer ${signedJwt}`,
"Content-Type": "application/x-www-form-urlencoded",
},
body,
});
return response.json();
};
(async () => {
const tokenResp = await getGoogleAccessToken();
console.log(tokenResp);
})();
你有(下面)沒有單引號
gapi.analytics.auth.authorize({
serverAuth: {
access_token: token
}
});
但是為了讓它工作,根據他們的文檔,你需要在serverAuth
和access_token
周圍加上單引號。
gapi.analytics.auth.authorize({
'serverAuth': {
'access_token': token
}
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.