从Firebase功能访问Google Site Verification API

时间:2017-08-21 12:05:07

标签: node.js firebase google-api google-cloud-functions

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

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

我编写了以下示例,我尝试在本地运行(模拟函数环境)并远程运行Firebase函数:

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项目启用了网站验证API。

更新

使用项目所有者角色创建服务帐户并使用JWT方法进行身份验证会导致以下权限错误:

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云端控制台中配置某些权限,或者验证方法是否应该不同。我觉得只允许带有手动用户身份验证的OAuth 2.0客户端...

欢迎提供帮助。

1 个答案:

答案 0 :(得分:0)

网站验证API仅允许OAuth 2.0使用手动身份验证。入门文档包含以下几行:

  

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

作为一种解决方法,我生成了一个带有关联刷新令牌的访问令牌。一旦两者都有,您就可以在服务器功能上使用它们。如果您使用官方Google NodeJS client作为网站验证API,则会为您管理访问令牌刷新。否则,您必须在访问令牌过期时刷新它。

以下是您可以用来轻松创建访问令牌的Firebase功能。

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。这会重定向到包含授权代码作为查询参数的本地URL。获取此参数并调用与 oauth2GetAccessToken 关联的第二个HTTP端点。最后一次调用应返回您的访问权限并刷新令牌。

一旦您拥有这两个令牌,您就可以将它们存储在您的Firebase环境配置中(以及您的客户端ID和密码)并访问网站验证API,如下所示:

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) => {
        // ...
    });
}