代码之家  ›  专栏  ›  技术社区  ›  ololo

在经过身份验证的Google帐户下获取Google My Business帐户时出现未经授权的错误

  •  0
  • ololo  · 技术社区  · 4 年前

    我正试图在一个经过验证的谷歌账户下列出这些企业。我已经完成了Oauth2流,并得到了包含 access_token, id_token,refresh_token and expiry_date

    现在,当我尝试在该账户下列出业务时,我不断得到 Unauthorized Error .

    以下是我的流程:

    initOAuth2Client() {
        return new google.auth.OAuth2(
            process.env.GOOGLE_CLIENT_ID,
            process.env.GOOGLE_CLIENT_SECRET,
            process.env.GOOGLE_REDIRECT_URL
        );
    }
    
    //Authorization Code
    async authenticateAgainstGoogleMyBusiness() {
        let oauth2Client = module.exports.initOAuth2Client();
        const scopes = [
            'https://www.googleapis.com/auth/business.manage',
            'https://www.googleapis.com/auth/userinfo.profile'
        ];
        const state = ....
        const url = oauth2Client.generateAuthUrl({
            access_type: 'offline',
            scope: scopes,
            state: state,
            prompt: 'consent'
        });
    }
    

    然后对于我的Oauth回调处理程序,我有这个

    async googleOAuthCallbackHandler(req, res) {
        let oauth2Client = module.exports.initOAuth2Client();
        let { code, state } = req.query;
        const oauth2Client = module.exports.initOAuth2Client();
        const { tokens } = await oauth2Client.getToken(code);
        //this is where I saved the tokens exactly as received.
    }
    
      async fetchGoogleMyBusinessAccounts() { 
       let {access_token} = fetchTokenFromDatabase(); //This is how I retrieved the access tokens saved by the previous function.
    
        console.log(`Fetching GMB Accounts`);
        let accountsUrls = `https://mybusinessaccountmanagement.googleapis.com/v1/accounts`;
        try {
            let headers = {
                'Authorization': `Bearer ${access_token}`
            }
            let response = axios.get(accountsUrls, {
                headers: headers
            });
            let data = response.data;
            console.log(`GMB Accounts response = ${JSON.stringify(data, null, 2)}`);
        } catch (e) {
            console.log('Error retrieving GMB Accounts:Full error below:');
            console.log(e); //I keep getting Unauthorized even though I authorized the process on the oauth consent screen
        }
    }
    

    我该怎么解决这个问题?

    0 回复  |  直到 4 年前
        1
  •  1
  •   Linda Lawton - DaImTo    4 年前

    我想你应该看看样品 Google drive 我不知道为什么谷歌没有发布所有API的示例,但他们没有。我通过稍微修改谷歌驱动器的示例将其整合在一起。我现在还没有安装节点,但这应该很接近

    如果你有任何问题,请告诉我,我可以尝试帮助你调试它们。

    const fs = require('fs');
    const readline = require('readline');
    const {google} = require('googleapis');
    
    // If modifying these scopes, delete token.json.
    const SCOPES = ['https://www.googleapis.com/auth/business.manage'];
    // The file token.json stores the user's access and refresh tokens, and is
    // created automatically when the authorization flow completes for the first
    // time.
    const TOKEN_PATH = 'token.json';
    
    // Load client secrets from a local file.
    fs.readFile('credentials.json', (err, content) => {
      if (err) return console.log('Error loading client secret file:', err);
      // Authorize a client with credentials, then call the Google Drive API.
      authorize(JSON.parse(content), listFiles);
    });
    
    /**
     * Create an OAuth2 client with the given credentials, and then execute the
     * given callback function.
     * @param {Object} credentials The authorization client credentials.
     * @param {function} callback The callback to call with the authorized client.
     */
    function authorize(credentials, callback) {
      const {client_secret, client_id, redirect_uris} = credentials.installed;
      const oAuth2Client = new google.auth.OAuth2(
          client_id, client_secret, redirect_uris[0]);
    
      // Check if we have previously stored a token.
      fs.readFile(TOKEN_PATH, (err, token) => {
        if (err) return getAccessToken(oAuth2Client, callback);
        oAuth2Client.setCredentials(JSON.parse(token));
        callback(oAuth2Client);
      });
    }
    
    /**
     * Get and store new token after prompting for user authorization, and then
     * execute the given callback with the authorized OAuth2 client.
     * @param {google.auth.OAuth2} oAuth2Client The OAuth2 client to get token for.
     * @param {getEventsCallback} callback The callback for the authorized client.
     */
    function getAccessToken(oAuth2Client, callback) {
      const authUrl = oAuth2Client.generateAuthUrl({
        access_type: 'offline',
        scope: SCOPES,
      });
      console.log('Authorize this app by visiting this url:', authUrl);
      const rl = readline.createInterface({
        input: process.stdin,
        output: process.stdout,
      });
      rl.question('Enter the code from that page here: ', (code) => {
        rl.close();
        oAuth2Client.getToken(code, (err, token) => {
          if (err) return console.error('Error retrieving access token', err);
          oAuth2Client.setCredentials(token);
          // Store the token to disk for later program executions
          fs.writeFile(TOKEN_PATH, JSON.stringify(token), (err) => {
            if (err) return console.error(err);
            console.log('Token stored to', TOKEN_PATH);
          });
          callback(oAuth2Client);
        });
      });
    }
    
    /**
     * Lists the names and IDs of up to 10 files.
     * @param {google.auth.OAuth2} auth An authorized OAuth2 client.
     */
    function listFiles(auth) {
      const service = google.mybusinessaccountmanagement({version: 'v1', auth});
      service.accounts.get({
        pageSize: 10,
        fields: '*',
      }, (err, res) => {
        if (err) return console.log('The API returned an error: ' + err);
        const accounts= res.accounts;
        if (accounts.length) {
          console.log('accounts:');
          accounts.map((account) => {
            console.log(`${account.name} (${account.id})`);
          });
        } else {
          console.log('No files found.');
        }
      });
    }
    

    来自评论

    让我们从评论中看看这个错误消息。

    代码:429,错误:[{message:“超出了消费者'project_number:xxxxx'的服务'mybusinessaccountmanagement.googleapis.com'的配额度量'Requests'和限制'Requests/minute'的配额。”,域:'global',原因:'rateLimitExceeded'}]}

    当你在谷歌云平台上创建项目时,你必须启用你要使用的api。

    enter image description here

    如果你回去检查它(提示管理按钮)在左边有一个关于配额的注释

    enter image description here

    每个api在启用时都有一个默认配额

    enter image description here

    配额是控制可以向api发出多少请求的内容。谷歌限制了我们,因为他们希望我们所有人都能使用api。他们不希望一个应用程序充斥整个系统。

    正如你所看到的,这个api的默认配额是0,这就是为什么你在没有提出任何请求的情况下就已经超过了限制。

    在这一页的顶部有一张纸条,上面写着

    在IAM中的“配额”页面上请求更多配额限制或查看其他服务的配额;管理

    经过大量挖掘,我设法找到了申请额外配额的表格链接 Usage limits 在这一页的最下面有一行写着

    如果您需要更高的限额,您可以提交标准配额申请。

    提交表格。我不知道你需要多长时间才能获得配额延期。