Реализация OAuth для использования с Business Profile API

Каждый запрос, отправляемый вашим приложением в Business Profile API, должен содержать токен авторизации. Этот токен идентифицирует пользователя или приложение в Google, что необходимо для доступа к Business Profile API. В вашем приложении для авторизации запросов должен использоваться протокол OAuth 2.0.

В этом руководстве описываются разные способы реализовать поддержку OAuth 2.0 на вашей платформе. Поддержка авторизации через аккаунт Google и OAuth базируется на технологии Google Identity Platform.

Подробнее об использовании Oauth 2.0 с приложениями веб-серверов читайте в этом руководстве.

Преимущества реализации OAuth 2.0:

  • Защита доступа к данным владельца компании.
  • Аутентификация владельца компании при входе в его аккаунт Google.
  • Проверка прав партнерской платформы или приложения получать или изменять данные об адресах с явного согласия владельца компании. Владелец компании может отозвать эти права.
  • Аутентификация партнерской платформы.
  • Возможность партнерской платформы выполнять онлайн- и офлайн-действия от имени владельца компании: отвечать на отзывы, создавать публикации, обновлять меню и т. п.

Доступ к API с помощью OAuth 2.0

Прежде чем начинать работу, вам понадобится создать проект Google Cloud и включить Business Profile API. Подробнее об этом рассказывается в руководстве по базовой настройке.

Чтобы создать учетные данные и настроить окно для получения согласия пользователей, выполните следующие действия:

  1. На странице Credentials (Учетные данные) в API Console нажмите Create credentials (Создать учетные данные) и выберите OAuth Client ID (Идентификатор клиента OAuth) в раскрывающемся списке.
  2. Выберите тип своего приложения, укажите необходимую информацию и нажмите Create (Создать).
  3. Нажмите Save (Сохранить).
  4. Обновите настройки окна запроса доступа OAuth. Здесь вы можете изменить название приложения и его логотип, а также добавить ссылку на условия использования и политику конфиденциальности своего сервиса.

На следующем рисунке показаны поля Application name (Название приложения) и Application logo (Логотип приложения) окна запроса доступа OAuth:

На следующем рисунке показаны дополнительные поля окна запроса доступа OAuth:

На следующем рисунке показан пример окна, которое увидит пользователь:

Способы внедрения OAuth 2.0

Для внедрения OAuth 2.0 можно использовать следующие технологии и инструменты:

Далее в этой статье приводится подробное описание каждого способа внедрения OAuth 2.0 в приложение.

Область авторизации

В качестве области авторизации OAuth необходимо указать одно из следующих значений:

  • https://www.googleapis.com/auth/business.manage
  • https://www.googleapis.com/auth/plus.business.manage

Область plus.business.manage более не поддерживается. Она остается доступной, чтобы обеспечить обратную совместимость существующих решений.

Клиентские библиотеки

В приведенных здесь примерах для конкретных языков программирования показана реализация OAuth 2.0 с помощью клиентских библиотек Google API. Чтобы выполнить код из примера, сначала необходимо установить клиентскую библиотеку для соответствующего языка.

Клиентские библиотеки доступны для следующих языков:

Вход с аккаунтом Google

Вход с аккаунтом Google – самый быстрый способ интеграции OAuth в вашу платформу. Это решение доступно для Android, iOS и других платформ, а также для сайтов.

Вход с аккаунтом Google – это безопасная система аутентификации, позволяющая пользователю выполнить вход с помощью своего аккаунта Google (того же аккаунта, который он использует в других сервисах Google). После того как пользователь выполнил вход, он может предоставить вашему приложению разрешение совершать вызовы Business Profile API и обменять код авторизации, необходимый для получения токенов доступа и обновления.

Автономный доступ

Вам может потребоваться совершать вызовы Business Profile API от имени пользователя, даже когда он не в сети. Внедрение этой функции рекомендуется для всех платформ. С ее помощью вы сможете управлять информацией о компаниях (например, изменять и просматривать ее) в любое время после того, как пользователь вошел в аккаунт и предоставил вам полномочия.

Предполагается, что пользователь уже вошел в свой аккаунт Google, разрешил вашему приложению делать вызовы Business Profile API и обменял код авторизации. Этот код в дальнейшем используется для получения токена обновления, а затем – токена доступа. Токен обновления можно сохранить в безопасном хранилище и в любой момент использовать для получения нового токена доступа. Подробнее об этом рассказывается в статье Вход с аккаунтом Google для приложений на стороне сервера.

В приведенном ниже примере кода показано, как реализовать автономный доступ в приложении. О том, как выполнить этот код, рассказывается здесь.

<!-- The top of file index.html -->
<html itemscope itemtype="http://schema.org/Article">
<head>
  <!-- BEGIN Pre-requisites -->
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js">
  </script>
  <script src="https://apis.google.com/js/client:platform.js?onload=start" async defer>
  </script>
  <!-- END Pre-requisites -->
<!-- Continuing the <head> section -->
  <script>
    function start() {
      gapi.load('auth2', function() {
        auth2 = gapi.auth2.init({
          client_id: 'YOUR_CLIENT_ID.apps.googleusercontent.com',
          // Scopes to request in addition to 'profile' and 'email'
          scope: 'https://www.googleapis.com/auth/business.manage',
          immediate: true
        });
      });
    }
  </script>
</head>
<body>
  <!-- Add where you want your sign-in button to render -->
<!-- Use an image that follows the branding guidelines in a real app, more info here:
 https://developers.google.com/identity/branding-guidelines
-->
<h1>Business Profile Offline Access Demo</h1>

<p> This demo demonstrates the use of Google Identity Services and OAuth to gain authorization to call the Business Profile APIs on behalf of the user, even when the user is offline.

When a refresh token is acquired, store this token securely on your database. You will then be able to use this token to refresh the OAuth credentials and make offline API calls on behalf of the user. 

The user may revoke access at any time from the <a href='https://myaccount.google.com/permissions'>Account Settings</a> page.
</p>

<button id="signinButton">Sign in with Google</button><br>
<input id="authorizationCode" type="text" placeholder="Authorization Code" style="width: 60%"><button id="accessTokenButton" disabled>Retrieve Access/Refresh Token</button><br>
 <input id="refreshToken" type="text" placeholder="Refresh Token, never expires unless revoked" style="width: 60%"><button id="refreshSubmit">Refresh Access Token</button><br>
 <input id="accessToken" type="text" placeholder="Access Token" style="width: 60%"><button id="gmbAccounts">Get Business Profile Accounts</button><br>
 <p>API Responses:</p>
<script>
    //Will be populated after sign in.
    var authCode;
  $('#signinButton').click(function() {
    // signInCallback
    auth2.grantOfflineAccess().then(signInCallback);
  });

  $('#accessTokenButton').click(function() {
    // signInCallback defined in step 6.
    retrieveAccessTokenAndRefreshToken(authCode);
  });

  $('#refreshSubmit').click(function() {
    // signInCallback defined in step 6.
    retrieveAccessTokenFromRefreshToken($('#refreshToken').val());
  });

   $('#gmbAccounts').click(function() {
    // signInCallback defined in step 6.
    retrieveGoogleMyBusinessAccounts($('#accessToken').val());
  });




function signInCallback(authResult) {
    //the 'code' field from the response, used to retrieve access token and bearer token
  if (authResult['code']) {
    // Hide the sign-in button now that the user is authorized, for example:
    $('#signinButton').attr('style', 'display: none');
    authCode = authResult['code'];

    $("#accessTokenButton").attr( "disabled", false );

    //Pretty print response
    var e = document.createElement("pre")
    e.innerHTML = JSON.stringify(authResult, undefined, 2);
    document.body.appendChild(e);

    //autofill authorization code input
    $('#authorizationCode').val(authResult['code'])

    
  } else {
    // There was an error.
  }
}

//WARNING: THIS FUNCTION IS DISPLAYED FOR DEMONSTRATION PURPOSES ONLY. YOUR CLIENT_SECRET SHOULD NEVER BE EXPOSED ON THE CLIENT SIDE!!!!
function retrieveAccessTokenAndRefreshToken(code) {
      $.post('https://www.googleapis.com/oauth2/v4/token',
      { //the headers passed in the request
        'code' : code,
        'client_id' : 'YOUR_CLIENT_ID.apps.googleusercontent.com',
        'client_secret' : 'YOUR_CLIENT_SECRET',
        'redirect_uri' : 'http://localhost:8000',
        'grant_type' : 'authorization_code'
      },
      function(returnedData) {
        console.log(returnedData);
        //pretty print JSON response
        var e = document.createElement("pre")
        e.innerHTML = JSON.stringify(returnedData, undefined, 2);
        document.body.appendChild(e);
        $('#refreshToken').val(returnedData['refresh_token'])
      });
}

//WARNING: THIS FUNCTION IS DISPLAYED FOR DEMONSTRATION PURPOSES ONLY. YOUR CLIENT_SECRET SHOULD NEVER BE EXPOSED ON THE CLIENT SIDE!!!!
function retrieveAccessTokenFromRefreshToken(refreshToken) {
    $.post('https://www.googleapis.com/oauth2/v4/token', 
        { // the headers passed in the request
        'refresh_token' : refreshToken,
        'client_id' : 'YOUR_CLIENT_ID.apps.googleusercontent.com',
        'client_secret' : 'YOUR_CLIENT_SECRET',
        'redirect_uri' : 'http://localhost:8000',
        'grant_type' : 'refresh_token'
      },
      function(returnedData) {
        var e = document.createElement("pre")
        e.innerHTML = JSON.stringify(returnedData, undefined, 2);
        document.body.appendChild(e);
        $('#accessToken').val(returnedData['access_token'])
      });
}

function retrieveGoogleMyBusinessAccounts(accessToken) {
    $.ajax({
        type: 'GET',
        url: 'https://mybusinessaccountmanagement.googleapis.com/v1/accounts',
        headers: {
            'Authorization' : 'Bearer ' + accessToken
        },
        success: function(returnedData) {
            var e = document.createElement("pre")
            e.innerHTML = JSON.stringify(returnedData, undefined, 2);
            document.body.appendChild(e);
        }
    });
}
</script>
</body>
</html>

Только онлайн-доступ

Чтобы упростить реализацию, можно совершать вызовы Business Profile API без кеширования токенов обновления. Однако тогда платформа сможет совершать вызовы API от имени пользователя, только если этот пользователь вошел в свой аккаунт.

В приведенном ниже примере кода показано, как реализовать поддержку входа с аккаунтом Google и как совершить вызов API от имени конкретного пользователя. После того как пользователь совершает вход, используя свой аккаунт Google, и предоставляет согласие вашему приложению, вы получаете токен доступа. Этот токен доступа является идентификатором пользователя. Токен нужно указать в заголовке запроса Business Profile API.

О том, как выполнить этот код, рассказывается здесь.

<!-- The top of file index.html -->
<html lang="en">
  <head>
    <meta name="google-signin-scope" content="profile email https://www.googleapis.com/auth/business.manage">
    <meta name="google-signin-client_id" content="YOUR_CLIENT_ID.apps.googleusercontent.com">
    <script src="https://apis.google.com/js/platform.js" async defer></script>
  </head>
  <body>
    <div class="g-signin2" data-onsuccess="onSignIn" data-theme="dark"></div>
    <script>
      var gmb_api_version = 'https://mybusinessaccountmanagement.googleapis.com/v1';
      function onSignIn(googleUser) {
        // Useful data for your client-side scripts:
        var profile = googleUser.getBasicProfile();
        console.log('Full Name: ' + profile.getName());
        console.log("Email: " + profile.getEmail());
        var access_token = googleUser.getAuthResponse().access_token;

        //Using the sign in data to make a Business Profile APIs call
        var req = gmb_api_version + '/accounts';
        var xhr = new XMLHttpRequest();
        xhr.open('GET', req);
        xhr.setRequestHeader('Authorization', 'Bearer ' + access_token);

        //Displaying the API response
        xhr.onload = function () {
          document.body.appendChild(document.createTextNode(xhr.responseText));
        }
        xhr.send();
      }
    </script>
  </body>
</html>

Выполнение кода из примера

Чтобы выполнить код из приведенного здесь примера, сделайте следующее:

  1. Сохраните фрагмент кода в файле с названием index.html. Укажите в этом файле свой идентификатор клиента.
  2. Запустите веб-сервер из своего рабочего каталога. Для этого используйте следующую команду:

    Python 2.X

    python -m SimpleHTTPServer 8000

    Python 3.X

    python -m http.server 8000
  3. На странице Credentials (Учетные данные) в API Console выберите используемый идентификатор клиента.

  4. В поле Authorized JavaScript origins (Разрешенные источники JavaScript) укажите URL своего сайта. Чтобы выполнить код из примера в этом руководстве, необходимо также добавить URL http://localhost:8000.

  5. Загрузите следующий URL в браузере:

    http://localhost:8000/index.html
    
    .