Использование модели токена

Библиотека JavaScript google.accounts.oauth2 помогает запрашивать согласие пользователя и получать токен доступа для работы с его данными. Она основана на неявном предоставлении прав доступа OAuth 2.0 и позволяет вызывать API Google напрямую с помощью REST и CORS, а также использовать нашу клиентскую библиотеку Google API для JavaScript (также известную как gapi.client ) для простого и гибкого доступа к нашим более сложным API.

Прежде чем получить доступ к защищенным данным пользователя из браузера, пользователи на вашем сайте запускают веб-процессы выбора учетной записи Google, входа в систему и получения согласия, а затем серверы OAuth Google выдают и возвращают токен доступа вашему веб-приложению.

В модели авторизации на основе токенов нет необходимости хранить токены обновления для каждого пользователя на вашем внутреннем сервере.

Рекомендуется следовать подходу, описанному здесь, а не методам, описанным в старом руководстве OAuth 2.0 для клиентских веб-приложений .

Предпосылки

Следуйте инструкциям в разделе «Настройка» , чтобы настроить экран согласия OAuth, получить идентификатор клиента и загрузить клиентскую библиотеку.

Инициализировать токен-клиент

Вызовите initTokenClient() , чтобы инициализировать новый клиент токена с идентификатором клиента вашего веб-приложения. Вам необходимо включить список из одной или нескольких областей, к которым пользователю необходимо получить доступ:

const client = google.accounts.oauth2.initTokenClient({
  client_id: 'YOUR_GOOGLE_CLIENT_ID',
  scope: 'https://www.googleapis.com/auth/calendar.readonly',
  callback: (response) => {
    ...
  },
});

Запустить поток токенов OAuth 2.0

Используйте метод requestAccessToken() для запуска UX-потока токена и получения токена доступа. Google предлагает пользователю:

  • Выберите свой аккаунт,
  • войдите в учетную запись Google, если вы еще не вошли в систему,
  • предоставьте согласие на доступ вашего веб-приложения к каждой запрошенной области.

Жест пользователя запускает поток токенов: <button onclick="client.requestAccessToken();">Authorize me</button>

Затем Google возвращает обработчику обратного вызова ответ TokenResponse содержащий токен доступа и список областей, к которым пользователь предоставил доступ, или ошибку.

Пользователи могут закрыть окно выбора учетной записи или окна входа в систему, в этом случае ваша функция обратного вызова не будет вызвана.

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

Инкрементальная авторизация — это политика и методология разработки приложений, применяемые для запроса доступа к ресурсам с использованием областей действия только по мере необходимости, а не сразу ко всем ресурсам. Пользователи могут одобрять или отклонять доступ к отдельным ресурсам, запрашиваемым вашим приложением. Это называется гранулярными разрешениями .

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

Однако есть исключения. Приложения Google Workspace Enterprise с делегированием полномочий на уровне домена или приложения, помеченные как «Доверенные» , обходят экран согласия на детализированные разрешения. В таких приложениях пользователи не увидят экран согласия на детализированные разрешения. Вместо этого ваше приложение либо получит все запрошенные области действия, либо не получит ни одной.

Более подробную информацию см. в разделе Как обрабатывать детализированные разрешения .

Инкрементная авторизация

Для веб-приложений следующие два высокоуровневых сценария демонстрируют инкрементную авторизацию с использованием:

  • Одностраничное приложение Ajax, часто использующее XMLHttpRequest с динамическим доступом к ресурсам.
  • Несколько веб-страниц, ресурсы разделены и управляются на каждой странице отдельно.

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

Аякс

Добавьте в приложение поддержку инкрементальной авторизации, выполнив несколько вызовов requestAccessToken() и используя параметр scope объекта OverridableTokenClientConfig для запроса отдельных областей в момент их необходимости и только при необходимости. В этом примере ресурсы будут запрашиваться и отображаться только после того, как пользователь жестом развернёт свёрнутый раздел контента.

Приложение Ajax
Инициализируйте клиент токена при загрузке страницы:
        const client = google.accounts.oauth2.initTokenClient({
          client_id: 'YOUR_GOOGLE_CLIENT_ID',
          callback: "onTokenResponse",
        });
      
Запросите согласие и получите токены доступа с помощью жестов пользователя, нажмите `+`, чтобы открыть:

Документы для чтения

Показать последние документы

          client.requestAccessToken(
            overrideConfig = ({
               scope = 'https://www.googleapis.com/auth/documents.readonly'
             })
           );
        

Предстоящие события

Показать информацию календаря

          client.requestAccessToken(
            overrideConfig = ({
               scope = 'https://www.googleapis.com/auth/calendar.readonly'
             })
           );
        

Показать фотографии

          client.requestAccessToken(
            overrideConfig = ({
               scope = 'https://www.googleapis.com/auth/photoslibrary.readonly'
             })
           );
        

Каждый вызов requestAccessToken инициирует момент согласия пользователя, ваше приложение будет иметь доступ только к тем ресурсам, которые требуются разделу, который пользователь решил развернуть, тем самым ограничивая совместное использование ресурсов по выбору пользователя.

Несколько веб-страниц

При проектировании с учетом поэтапной авторизации несколько страниц используются для запроса только тех областей, которые необходимы для загрузки страницы, что снижает сложность и необходимость совершать несколько вызовов для получения согласия пользователя и получения токена доступа.

Многостраничное приложение
веб-страница Код
Страница 1. Документы для чтения
  const client = google.accounts.oauth2.initTokenClient({
    client_id: 'YOUR_GOOGLE_CLIENT_ID',
    callback: "onTokenResponse",
    scope: 'https://www.googleapis.com/auth/documents.readonly',
  });
  client.requestAccessToken();
          
Страница 2. Предстоящие события
  const client = google.accounts.oauth2.initTokenClient({
    client_id: 'YOUR_GOOGLE_CLIENT_ID',
    callback: "onTokenResponse",
    scope: 'https://www.googleapis.com/auth/calendar.readonly',
  });
  client.requestAccessToken();
          
Страница 3. Фото-карусель
  const client = google.accounts.oauth2.initTokenClient({
    client_id: 'YOUR_GOOGLE_CLIENT_ID',
    callback: "onTokenResponse",
    scope: 'https://www.googleapis.com/auth/photoslibrary.readonly',
  });
  client.requestAccessToken();
          

Каждая страница запрашивает необходимую область действия и получает токен доступа, вызывая initTokenClient() и requestAccessToken() во время загрузки. В этом сценарии отдельные веб-страницы используются для чёткого разделения пользовательского функционала и ресурсов по областям действия. В реальной ситуации отдельные страницы могут запрашивать несколько связанных областей действия.

Детальные разрешения

Детализированные разрешения обрабатываются одинаково во всех сценариях. После того, как requestAccessToken() вызовет вашу функцию обратного вызова и вернёт токен доступа, проверьте, одобрил ли пользователь запрошенные области действия, с помощью hasGrantedAllScopes() или hasGrantedAnyScope() . Например:

const client = google.accounts.oauth2.initTokenClient({
  client_id: 'YOUR_GOOGLE_CLIENT_ID',
  scope: 'https://www.googleapis.com/auth/calendar.readonly \
          https://www.googleapis.com/auth/documents.readonly \
          https://www.googleapis.com/auth/photoslibrary.readonly',
  callback: (tokenResponse) => {
    if (tokenResponse && tokenResponse.access_token) {
      if (google.accounts.oauth2.hasGrantedAnyScope(tokenResponse,
          'https://www.googleapis.com/auth/photoslibrary.readonly')) {
        // Look at pictures
        ...
      }
      if (google.accounts.oauth2.hasGrantedAllScopes(tokenResponse,
          'https://www.googleapis.com/auth/calendar.readonly',
          'https://www.googleapis.com/auth/documents.readonly')) {
        // Meeting planning and review documents
        ...
      }
    }
  },
});

Любые ранее принятые разрешения из предыдущих сеансов или запросов также будут включены в ответ. Запись о согласии пользователя сохраняется для каждого пользователя и идентификатора клиента и сохраняется при нескольких вызовах initTokenClient() или requestAccessToken() . По умолчанию согласие пользователя требуется только при первом посещении вашего веб-сайта и запросе новой области действия, но его можно запрашивать при каждой загрузке страницы с помощью prompt=consent в объектах конфигурации Token Client.

Работа с токенами

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

Использование REST и CORS с API Google

Токен доступа можно использовать для отправки аутентифицированных запросов к API Google с использованием REST и CORS. Это позволяет пользователям входить в систему, давать согласие, Google выдавать токен доступа, а вашему сайту — работать с данными пользователя.

В этом примере просмотрите предстоящие события календаря вошедшего в систему пользователя, используя токен доступа, возвращаемый tokenRequest() :

var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://www.googleapis.com/calendar/v3/calendars/primary/events');
xhr.setRequestHeader('Authorization', 'Bearer ' + tokenResponse.access_token);
xhr.send();

Подробнее см. в статье Как использовать CORS для доступа к API Google .

В следующем разделе рассказывается, как легко интегрироваться с более сложными API.

Работа с библиотекой JavaScript API Google

Клиент токена работает с клиентской библиотекой Google API для JavaScript. См. фрагмент кода ниже.

const client = google.accounts.oauth2.initTokenClient({
  client_id: 'YOUR_GOOGLE_CLIENT_ID',
  scope: 'https://www.googleapis.com/auth/calendar.readonly',
  callback: (tokenResponse) => {
    if (tokenResponse && tokenResponse.access_token) {
      gapi.client.setApiKey('YOUR_API_KEY');
      gapi.client.load('calendar', 'v3', listUpcomingEvents);
    }
  },
});

function listUpcomingEvents() {
  gapi.client.calendar.events.list(...);
}

Срок действия токена

По умолчанию токены доступа имеют короткий срок действия. Если срок действия токена доступа истекает до окончания сеанса пользователя, получите новый токен, вызвав метод requestAccessToken() из события, инициированного пользователем, например, нажатия кнопки.

Вызовите метод google.accounts.oauth2.revoke , чтобы отозвать согласие пользователя и доступ к ресурсам для всех областей действия, предоставленных вашему приложению. Для отзыва этого разрешения требуется действительный токен доступа:

google.accounts.oauth2.revoke('414a76cb127a7ece7ee4bf287602ca2b56f8fcbf7fcecc2cd4e0509268120bd7', done => {
    console.log(done);
    console.log(done.successful);
    console.log(done.error);
    console.log(done.error_description);
  });