如何获取 Google 服务帐户访问令牌 javascript

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28751995/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 09:29:47  来源:igfitidea点击:

How to obtain Google service account access token javascript

javascriptgoogle-analytics-api

提问by Rothrock

I'm trying to set up an analytics dashboard of my site for my leadership to view site usage. I don't want them to have to have a google account or to add them individual to see the results.

我正在尝试为我的网站设置一个分析仪表板,以便我的领导查看网站使用情况。我不希望他们必须拥有谷歌帐户或单独添加他们才能查看结果。

I've set up a service account and OAuth2 access. All the tutorials I find show code like this:

我已经设置了一个服务帐户和 OAuth2 访问权限。我找到的所有教程都显示如下代码:

gapi.analytics.auth.authorize({
  clientid: 'Service account client ID',
  serverAuth: {
      access_token: 'XXXXXXXXXXXXXXXXX'
}

And all the documentation talks about "...once you recieve your access token...." But none of them actually say how to get that! I see Certificate Fingerprints, Public key fingerprints. I also see how to generate JSON and P12 keys. I don't see how to generate the access token.

所有的文档都在谈论“......一旦你收到你的访问令牌......”但是他们实际上没有说如何获得它!我看到证书指纹,公钥指纹。我还看到了如何生成 JSON 和 P12 密钥。我不知道如何生成访问令牌。

Can someone explain how to do this?

有人可以解释如何做到这一点吗?

I found this. It explains that I need the key file and that it is a bad idea, but doesn't say how to actually do it.

我找到了这个。它解释了我需要密钥文件并且这是一个坏主意,但没有说明如何实际操作。

I also found this. But I don't know anything about Node.js and I'm hoping that is just one possible route?

我也发现了这个。但我对 Node.js 一无所知,我希望这只是一种可能的途径?

回答by Rothrock

Finally got it working! Using kjur's jsjws pure JavaScript implementation of JWT. I used this demoas the basis for generating the JWT to request the token. Here are the steps

终于让它工作了!使用 kjur 的 jsjws 纯 JavaScript 实现 JWT。我使用这个演示作为生成 JWT 来请求令牌的基础。以下是步骤

In the Google Developers console I created a service account. Here are instructions for that

在 Google Developers 控制台中,我创建了一个服务帐户。以下是相关说明

In the Google API console I added the service account to the credentials. I then generated a new JSON key. This gives me my private keyin plain text format.

在 Google API 控制台中,我将服务帐户添加到凭据中。然后我生成了一个新的 JSON 密钥。这以纯文本格式为我提供了我的私钥

I then followed these instructions from google on making an authorized API call using HTTP/REST.

然后我按照谷歌的这些说明使用 HTTP/REST 进行授权的 API 调用。

This is the required header information.

这是必需的标题信息。

var pHeader = {"alg":"RS256","typ":"JWT"}
var sHeader = JSON.stringify(pHeader);

And the claim set is something like this. (This is using syntax that is supplied by the KJUR JWT library described above.)

声明集是这样的。(这是使用由上述 KJUR JWT 库提供的语法。)

var pClaim = {};
pClaim.aud = "https://www.googleapis.com/oauth2/v3/token";
pClaim.scope = "https://www.googleapis.com/auth/analytics.readonly";
pClaim.iss = "<[email protected]";
pClaim.exp = KJUR.jws.IntDate.get("now + 1hour");
pClaim.iat = KJUR.jws.IntDate.get("now");

var sClaim = JSON.stringify(pClaim);

The the controversial bit is putting my private key into the client side code. For this usage it isn't that bad (I don't think.) First, the site is behind our corporate firewall, so who is going to "hack" it? Second, even if someone did get it, the service account's only authorization is to view our analytics data -- which is the purpose of my dashboard is that anybody who visits the page can view our analytics data. Not going to post the private key here, but basically like so.

有争议的一点是将我的私钥放入客户端代码中。对于这种用法,它并没有那么糟糕(我不认为)。首先,该站点位于我们的公司防火墙后面,那么谁会“破解”它?其次,即使有人确实得到了它,服务帐户的唯一授权是查看我们的分析数据——这是我仪表板的目的,任何访问该页面的人都可以查看我们的分析数据。不打算在这里发布私钥,但基本上是这样。

var key = "-----BEGIN PRIVATE KEY-----\nMIIC....\n-----END PRIVATE KEY-----\n";`enter code here`

Then generated a signed JWT with

然后生成一个签名的 JWT

 var sJWS = KJUR.jws.JWS.sign(null, sHeader, sClaim, key);

After that I used XMLHttpRequest to call the google API. I tried to use FormData with the request but that didn't work. So the old(er) school

之后我使用 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)

After that I have my access token and I can follow these tutorialson using the embed API, but authorizing like so:

之后我有了我的访问令牌,我可以按照这些教程使用嵌入 API,但授权如下:

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

Don't forget that you have to give the service account permission to view the content, just like any other user. And of course, it would be a really bad idea if the service account was authorized to do anything other than read only.

不要忘记,您必须授予服务帐户查看内容的权限,就像任何其他用户一样。当然,如果服务帐户被授权做只读以外的任何事情,那将是一个非常糟糕的主意。

There are probably also issues with regards to timing and token expiring that I will run into, but so far so good.

我可能会遇到与时间和令牌到期有关的问题,但到目前为止一切顺利。

回答by hwrod

You can use the official (and alpha) Google API for Node.js to generate the token. It's helpful if you have a service account.

您可以使用 Node.js 的官方(和 alpha)Google API 来生成令牌。如果您有服务帐户,这会很有帮助。

On the server:

在服务器上:

npm install -S googleapis

ES6:

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`
})

回答by user3051556

You have (below) without single quotes

你有(下面)没有单引号

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

but for it to work, as per their documentation you need to put single quotes around serverAuthand access_token.

但是为了让它工作,根据他们的文档,你需要在serverAuth和周围加上单引号access_token

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