【问题标题】:Accessing Google Site Verification API from a Firebase function从 Firebase 函数访问 Google Site Verification API
【发布时间】:2018-01-29 12:04:36
【问题描述】:

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

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

我编写了以下示例,我尝试在本地(模拟函数环境)和远程在 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.' } ] }

此错误是因为我使用 API 资源管理器使用相同 ID 进行了调用,并且此调用返回了详细信息。

不知道是不是一定要在谷歌云控制台中配置一些权限,还是认证方式应该不同。我感觉只允许使用手动用户身份验证的 OAuth 2.0 客户端...

欢迎帮助。

【问题讨论】:

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


    【解决方案1】:

    站点验证 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) => {
            // ...
        });
    }
    

    【讨论】:

      猜你喜欢
      • 2014-11-28
      • 2017-02-13
      • 2014-10-13
      • 2017-09-13
      • 2014-03-16
      • 2019-12-20
      • 1970-01-01
      • 2017-02-16
      • 2018-09-24
      相关资源
      最近更新 更多