在经过身份验证的 Google 帐户下获取 Google 我的企业帐户时发生未经授权的错误

Unauthorized Error when Fetching Google My Business accounts under an Authenticated Google Account

我正在尝试列出经过身份验证的 Google 帐户下的企业。我完成了 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
    }
}

我该如何解决这个问题?

我认为您应该查看 Google drive 的示例 我不知道为什么 Google 没有发布所有 API 的示例,但他们没有。我通过稍微更改 google 驱动器的示例来将其放在一起。我现在没有安装节点,但这应该是 close

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

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.');
    }
  });
}

来自评论

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

code: 429, errors: [ { message: "Quota exceeded for quota metric 'Requests' and limit 'Requests per minute' of service 'mybusinessaccountmanagement.googleapis.com' for consumer 'project_number:xxxxx'.", domain: 'global', reason: 'rateLimitExceeded' } ] }

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

如果您返回并通过左侧的(提示管理按钮)查看它,则会有关于配额的注释

每个 api 都有一个默认配额供您启用。此 api 的默认配额是

配额用于控制您可以向 api 发出多少请求。 Google 限制我们,因为他们希望我们所有人都能够使用 api。他们不希望只有一个应用程序充斥着系统。

如您所见,此 api 的默认配额为 0,这就是为什么您在没有发出任何请求的情况下已经超出限制的原因。

在此页面的顶部有一条注释,上面写着

Request more quota limits or view quotas for your other services on the Quotas page, found in IAM & admin.

经过大量挖掘,我设法在页面底部找到了一个 link 申请额外配额 Usage limits 的表格,其中有一行内容为

If you need higher limits, you can submit a Standard quota request.

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