从Firebasefunction访问Google Site Verification API

我正在尝试使用Node.js的Firebase函数使用Google Site Verification API 。

Github的google-api-nodejs-client存储库中提供的READMEbuild议使用默认的应用程序方法,而不是手动创buildOAuth2客户端,JWT客户端或计算客户端。

我写了下面的例子,我尝试在本地(模拟function环境)上运行,并在Firebasefunction上远程运行:

const google = require('googleapis'); google.auth.getApplicationDefault(function (err, authClient, projectId) { if (err) { console.log('Authentication failed because of ', err); return; } if (authClient.createScopedRequired && authClient.createScopedRequired()) { authClient = authClient.createScoped([ 'https://www.googleapis.com/auth/siteverification' ]); } const siteVerification = google.siteVerification({ version: 'v1', auth: authClient }); siteVerification.webResource.get({ id: 'test.com' }, {}, function (err, data) { if (err) { console.log('siteVerification get error:', err); } else { console.log('siteVerification result:', data); } }); }); 

在这两种情况下,执行后,我得到以下错误:

 siteVerification get error: { Error: A Forbidden error was returned while attempting to retrieve an access token for the Compute Engine built-in service account. This may be because the Compute Engine instance does not have the correct permission scopes specified. Insufficient Permission at Request._callback (/user_code/node_modules/googleapis/node_modules/google-auth-library/lib/transporters.js:85:15) at Request.self.callback (/user_code/node_modules/googleapis/node_modules/request/request.js:188:22) at emitTwo (events.js:106:13) at Request.emit (events.js:191:7) at Request.<anonymous> (/user_code/node_modules/googleapis/node_modules/request/request.js:1171:10) at emitOne (events.js:96:13) at Request.emit (events.js:188:7) at IncomingMessage.<anonymous> (/user_code/node_modules/googleapis/node_modules/request/request.js:1091:12) at IncomingMessage.g (events.js:292:16) at emitNone (events.js:91:20) code: 403, errors: [ { domain: 'global', reason: 'insufficientPermissions', message: 'Insufficient Permission' } ] } 

请注意,与Firebase关联的Cloud项目启用了站点validationAPI。

更新

使用Project所有者angular色创build服务帐户并使用JWT方法进行身份validation会导致以下权限错误:

 info: siteVerification get error: { Error: You are not an owner of this site. at Request._callback ... at IncomingMessage.g (events.js:292:16) at emitNone (events.js:91:20) code: 403, errors: [ { domain: 'global', reason: 'forbidden', message: 'You are not an owner of this site.' } ] } 

这个错误是为了得到一个我知道拥有的站点的ID,因为我使用API​​浏览器使用相同的ID进行了呼叫,并且这个返回了详细信息。

我不知道是否必须在Google云端控制台中configuration某些权限,或者authentication方式应该不同。 我有这样的感觉,只有OAuth 2.0手动用户身份validation客户端允许…

帮助是受欢迎的。

网站validationAPI只允许OAuth 2.0进行手动validation。 入门文档包含以下几行:

您的应用程序必须使用OAuth 2.0来授权请求​​。 没有其他授权协议被支持。 如果您的应用程序使用Googlelogin,则会为您处理授权的某些方面。

作为一种解决方法,我使用关联的刷新令牌生成了一个访问令牌。 一旦你们有了,你可以在你的服务器function上使用它们。 如果您使用官方Google NodeJS客户端作为站点validationAPI,则会为您pipe理访问令牌刷新。 否则,您必须刷新您的访问令牌到期。

以下是可用于轻松创build访问令牌的Firebasefunction。

 function oauth2Client() { return new google.auth.OAuth2( config.site_verification_api.client_id, config.site_verification_api.client_secret, 'http://localhost:8080/oauth' ); } exports.oauth2GetAuthorizationCode = functions.https.onRequest((req, res) => { const client = oauth2Client(); const url = client.generateAuthUrl({ access_type: 'offline', scope: [ 'https://www.googleapis.com/auth/siteverification' ] }); res.status(200).send({url: url}); }); exports.oauth2GetAccessToken = functions.https.onRequest((req, res) => { const client = oauth2Client(); const code = req.query.code; client.getToken(code, (err, tokens) => { if (!err) { res.status(200).send({tokens}); } else { console.error('Error while getting access token:', err); res.sendStatus(500); } }); }); 

当您调用与oauth2GetAuthorizationCode关联的HTTP端点时,将返回一个URL。 在浏览器中打开这个URL。 这将redirect到包含授权代码作为查询参数的本地URL。 获取此参数并调用与oauth2GetAccessToken关联的第二个HTTP端点。 这最后一次调用应该返回您的访问和刷新令牌。

获得两个令牌后,可以将其存储在Firebase环境configuration中(以及您的客户端ID和密码),并按以下方式访问站点validationAPI:

 function oauth2ClientWithCredentials() { const client = oauth2Client(); client.setCredentials({ access_token: config.site_verification_api.access_token, refresh_token: config.site_verification_api.refresh_token }); return client; } function invokeSiteVerificationApi() { const client = oauth2ClientWithCredentials(); const siteVerification = google.siteVerification({ version: 'v1', auth: client }); siteVerification.webResource.get({ id: 'dns%3A%2F%2F' + domain }, null, (err, result) => { // ... }); }