Руководство по переходу с внеполосного метода (OOB)

Обзор

16 февраля 2022 г. мы объявили о планах повысить безопасность взаимодействий с Google OAuth за счет использования более защищенных потоков OAuth. В этом руководстве рассказывается, как перейти с OAuth OOB на поддерживаемые альтернативные варианты.

Это защитная мера против фишинга и атак с имитацией приложений при взаимодействии с конечными точками авторизации Google OAuth 2.0.

Что такое OOB?

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

Процесс OOB будет прекращен для всех типов приложений, включая веб-приложения, приложения для Android, iOS, универсальной платформы Windows (UWP), приложения Chrome, телевизоров и устройств ввода с ограниченными возможностями, а также для компьютерных приложений.

Ключевые даты

  • 28 февраля 2022 г. – блокировка нового использования OAuth для OOB.
  • 5 сентября 2022 г. – для запросов OAuth, не соответствующих требованиям, может показываться пользовательское предупреждение.
  • 3 октября 2022 г. – поддержка OOB-процесса прекращена для клиентов OAuth, созданных до 28 февраля 2022 г.
  • 31 января 2023 г. – все существующие клиенты заблокированы (в том числе исключенные).

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

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

  1. Определите, затронет ли вас это изменение.
  2. Если вы используете этот фреймворк, перейдите на более безопасный способ авторизации.

Как определить, затронет ли вас это изменение

Это изменение касается только рабочих приложений, то есть тех, у которых статус публикации – Рабочая версия. Для приложений со статусом публикации "Тестирование" этот процесс не изменится.

Проверьте статус публикации в OAuth на странице Брендинг в консоли Google Cloud. Если вы используете процесс OOB в проекте со статусом "В рабочей среде", перейдите к следующему шагу.

Как определить, использует ли ваше приложение способ OOB

Проверьте код приложения или исходящий сетевой вызов (если в приложении используется библиотека OAuth), чтобы определить, используется ли в запросе авторизации Google OAuth, который отправляет ваше приложение, значение URI перенаправления OOB.

Проверьте код приложения

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

  • redirect_uri=urn:ietf:wg:oauth:2.0:oob
  • redirect_uri=urn:ietf:wg:oauth:2.0:oob:auto
  • redirect_uri=oob

Пример запроса для перенаправления вне браузера:

https://accounts.google.com/o/oauth2/v2/auth?
response_type=code&
scope=<SCOPES>&
state=<STATE>&
redirect_uri=urn:ietf:wg:oauth:2.0:oob&
client_id=<CLIENT_ID>

Проверка исходящего сетевого вызова

Способ проверки сетевых вызовов зависит от типа приложения.

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

  • redirect_uri=urn:ietf:wg:oauth:2.0:oob
  • redirect_uri=urn:ietf:wg:oauth:2.0:oob:auto
  • redirect_uri=oob

Пример запроса для перенаправления вне браузера:

https://accounts.google.com/o/oauth2/v2/auth?
response_type=code&
scope=<SCOPES>&
state=<STATE>&
redirect_uri=urn:ietf:wg:oauth:2.0:oob&
client_id=<CLIENT_ID>

Перейдите на безопасную альтернативу

Мобильные клиенты (Android и iOS)

Если вы обнаружите, что в вашем приложении используется OOB-авторизация с типом приложения OAuth для Android или iOS, перейдите на рекомендуемые SDK (Android, iOS).

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

По ссылкам на документацию ниже вы найдете информацию о том, как использовать рекомендуемые SDK для доступа к API Google без URI перенаправления OOB.

Доступ к API Google на Android

Клиентский доступ

В примере ниже показано, как получить доступ к API Google на стороне клиента в Android с помощью рекомендуемой библиотеки сервисов идентификации Google для Android.

List<Scopes> requestedScopes = Arrays.asList(DriveScopes.DRIVE_APPDATA);
AuthorizationRequest authorizationRequest =
    AuthorizationRequest.builder()
        .setRequestedScopes(requestedScopes)
        .build();
Identity.getAuthorizationClient(activity)
    .authorize(authorizationRequest)
    .addOnSuccessListener(
        authorizationResult -> {
          if (authorizationResult.hasResolution()) {
            // Access needs to be granted by the user
            PendingIntent pendingIntent =
                authorizationResult.getPendingIntent();
            try {
              startIntentSenderForResult(
                  pendingIntent.getIntentSender(),
                  REQUEST_AUTHORIZE, null, 0, 0, 0, null);
            } catch (IntentSender.SendIntentException e) {
              Log.e(
                  TAG,
                  "Couldn't start Authorization UI: "
                      + e.getLocalizedMessage());
            }
          } else {
            // Access already granted, continue with user action
            saveToDriveAppFolder(authorizationResult);
          }
        })
    .addOnFailureListener(e -> Log.e(TAG, "Failed to authorize", e));

Передайте authorizationResult в определенный вами метод, чтобы сохранить контент в папке пользователя на Диске. В классе authorizationResult есть метод getAccessToken(), который возвращает токен доступа.

Доступ на стороне сервера (офлайн)

В примере ниже показано, как получить доступ к API Google на стороне сервера в Android.

List<Scopes> requestedScopes = Arrays.asList(DriveScopes.DRIVE_APPDATA);
AuthorizationRequest authorizationRequest =
    AuthorizationRequest.builder()
        .requestOfflineAccess(webClientId)
        .setRequestedScopes(requestedScopes)
        .build();
Identity.getAuthorizationClient(activity)
    .authorize(authorizationRequest)
    .addOnSuccessListener(
        authorizationResult -> {
          if (authorizationResult.hasResolution()) {
            // Access needs to be granted by the user
            PendingIntent pendingIntent =
                authorizationResult.getPendingIntent();
            try {
              startIntentSenderForResult(
                  pendingIntent.getIntentSender(),
                  REQUEST_AUTHORIZE, null, 0, 0, 0, null);
            } catch (IntentSender.SendIntentException e) {
              Log.e(
                  TAG,
                  "Couldn't start Authorization UI: "
                      + e.getLocalizedMessage());
            }
          } else {
            String authCode =
                authorizationResult.getServerAuthCode();
          }
        })
    .addOnFailureListener(e -> Log.e(TAG, "Failed to authorize", e));

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

Как получить доступ к API Google в приложении для iOS

Клиентский доступ

В примере ниже показано, как получить доступ к API Google на стороне клиента в iOS.

user.authentication.do { authentication, error in
  guard error == nil else { return }
  guard let authentication = authentication else { return }
  
  // Get the access token to attach it to a REST or gRPC request.
  let accessToken = authentication.accessToken
  
  // Or, get an object that conforms to GTMFetcherAuthorizationProtocol for
  // use with GTMAppAuth and the Google APIs client library.
  let authorizer = authentication.fetcherAuthorizer()
}

Используйте токен доступа для вызова API, включив его в заголовок запроса REST или gRPC (Authorization: Bearer ACCESS_TOKEN) или используя авторизатор средства извлечения (GTMFetcherAuthorizationProtocol) с клиентской библиотекой API Google для Objective-C для REST.

Ознакомьтесь с руководством по клиентскому доступу, чтобы узнать, как получить доступ к API Google на стороне клиента.

Доступ на стороне сервера (офлайн)

В примере ниже показано, как получить доступ к API Google на стороне сервера для поддержки клиента iOS.

GIDSignIn.sharedInstance.signIn(
    with: signInConfig, presenting: self
) { user, error in
  guard error == nil else { return }
  guard let user = user else { return }
  
  // request a one-time authorization code that your server exchanges for
  // an access token and refresh token
  let authCode = user.serverAuthCode
}

Ознакомьтесь с руководством по доступу на стороне сервера, чтобы узнать, как получить доступ к API Google на стороне сервера.

Клиент приложения Chrome

Если вы обнаружите, что ваше приложение использует OOB-авторизацию в клиенте приложения Chrome, перейдите на Chrome Identity API.

В примере ниже показано, как получить все контакты пользователя без использования URI переадресации OOB.

window.onload = function() {
  document.querySelector('button').addEventListener('click', function() {

  
  // retrieve access token
  chrome.identity.getAuthToken({interactive: true}, function(token) {
  
  // ..........


  // the following example shows how to use a retrieved access token with an
  // appropriate scope to call the Google People API contactGroups.get endpoint

  fetch(
    'https://people.googleapis.com/v1/contactGroups/all'
        + '?maxMembers=20&key=API_KEY',
    init)
    .then((response) => response.json())
    .then(function(data) {
      console.log(data)
    });
   });
 });
};

Дополнительную информацию о том, как аутентифицировать пользователей и вызывать конечные точки Google с помощью Chrome Identity API, можно найти в руководстве по Chrome Identity API.

Веб-приложение

Если вы обнаружите, что ваше веб-приложение использует OOB, перейдите на одну из клиентских библиотек Google API. Ознакомьтесь со списком клиентских библиотек Google API для разных языков программирования.

Библиотеки упрощают доступ к API Google и обрабатывают все вызовы конечных точек Google.

Доступ на стороне сервера (офлайн)

Чтобы использовать режим доступа на стороне сервера (офлайн), выполните следующие действия :

  • Настройте сервер и определите общедоступную конечную точку (URI перенаправления) для получения кода авторизации.
  • Настройте URI перенаправления на странице Клиенты в консоли Google Cloud.

В приведенном ниже фрагменте кода показано, как использовать Google Drive API в NodeJS, чтобы получить список файлов пользователя на Google Диске на стороне сервера без использования URI перенаправления OOB.

async function main() {
  const server = http.createServer(async function (req, res) {

  if (req.url.startsWith('/oauth2callback')) {
    let q = url.parse(req.url, true).query;

    if (q.error) {
      console.log('Error:' + q.error);
    } else {
      
      // Get access and refresh tokens (if access_type is offline)
      let { tokens } = await oauth2Client.getToken(q.code);
      oauth2Client.setCredentials(tokens);

      // Example of using Google Drive API to list filenames in user's Drive.
      const drive = google.drive('v3');
      drive.files.list({
        auth: oauth2Client,
        pageSize: 10,
        fields: 'nextPageToken, files(id, name)',
      }, (err1, res1) => {
        // TODO(developer): Handle response / error.
      });
    }
  }
}

Ознакомьтесь с руководством по веб-приложениям на стороне сервера, чтобы узнать, как получить доступ к API Google со стороны сервера.

Клиентский доступ

В следующем фрагменте кода на JavaScript показан пример использования Google API для доступа к мероприятиям из календаря пользователя на стороне клиента.


// initTokenClient() initializes a new token client with your
// web app's client ID and the scope you need access to

const client = google.accounts.oauth2.initTokenClient({
  client_id: 'YOUR_GOOGLE_CLIENT_ID',
  scope: 'https://www.googleapis.com/auth/calendar.readonly',
  
  // callback function to handle the token response
  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(...);
}

Ознакомьтесь с руководством по клиентским веб-приложениям, чтобы узнать, как получить доступ к API Google со стороны клиента.

Клиент для ПК

Если вы обнаружите, что ваше приложение использует OOB-процесс в клиенте для компьютеров, вам следует перейти на процесс с замыканием IP-адреса на себя (localhost или 127.0.0.1).