簡體   English   中英

如何獲取 Google 服務帳戶訪問令牌 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
    }
});

但是為了讓它工作,根據他們的文檔,你需要在serverAuthaccess_token周圍加上單引號。

gapi.analytics.auth.authorize({
    'serverAuth': {
        'access_token': token
    }
});

暫無
暫無

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

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