Руководство по миграции потока IP-адресов с обратной связью

Обзор

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

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

Что такое поток IP-адреса обратной связи?

Использование IP-адреса замыкающей петли (loopback IP address) позволяет использовать IP-адрес замыкающей петли или localhost в качестве хост-компонента URI перенаправления, куда отправляются учетные данные после того, как пользователь подтвердит запрос на согласие OAuth. Этот поток уязвим для атак типа « человек посередине », когда вредоносное приложение, обращающееся к тому же интерфейсу замыкающей петли в некоторых операционных системах, может перехватить ответ от сервера авторизации на заданный URI перенаправления и получить доступ к коду авторизации.

Использование IP-адреса обратной связи для нативных клиентов OAuth в iOS, Android и Chrome прекращается, но будет по-прежнему поддерживаться в настольных приложениях.

Ключевые сроки соблюдения требований

  • 14 марта 2022 г. — новым клиентам OAuth заблокирован доступ к потоку IP-адресов Loopback.
  • 1 августа 2022 г. — для запросов OAuth, не соответствующих требованиям, может отображаться предупреждающее сообщение, видимое пользователю.
  • 31 августа 2022 г. — блокировка потока IP-адресов Loopback для нативных клиентов OAuth Android, Chrome и iOS, созданных до 14 марта 2022 г.
  • 21 октября 2022 г. - все существующие клиенты заблокированы (включая клиентов, на которых распространяется исключение).

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

Для завершения процесса миграции необходимо выполнить два основных шага:
  1. Определите, затрагивает ли это вас.
  2. Если вас это затронуло, перейдите на поддерживаемую альтернативную платформу.

Определите, затрагивает ли это вас.

Проверьте тип идентификатора клиента OAuth.

Перейдите на страницу «Клиенты» в консоли Google Cloud и найдите свой тип идентификатора клиента OAuth в разделе « Идентификаторы клиентов OAuth 2.0» . Это может быть один из следующих типов: веб-приложение , Android , iOS , универсальная платформа Windows (UWP) , приложение Chrome , телевизоры и устройства с ограниченным вводом , настольное приложение .

Перейдите к следующему шагу, если вы используете Android, приложение Chrome или iOS и применяете протокол с использованием IP-адреса замыкания (loopback IP address).

Если вы используете поток аутентификации по IP-адресу замыкания на землю в клиенте OAuth настольного приложения, вам не нужно ничего делать в связи с этим прекращением поддержки, поскольку использование с этим типом клиента OAuth будет по-прежнему поддерживаться.

Как определить, использует ли ваше приложение поток IP-адреса обратной связи?

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

Проверьте код вашего приложения.

Просмотрите раздел кода вашего приложения, где вы обращаетесь к конечным точкам авторизации Google OAuth, и определите, принимает ли параметр redirect_uri какое-либо из следующих значений:
  • redirect_uri=http://127.0.0.1: <port> например redirect_uri=http://127.0.0.1: 3000
  • redirect_uri=http://[::1]: <port> например redirect_uri=http://[::1]: 3000
  • redirect_uri=http://localhost: <port> например, redirect_uri=http://localhost: 3000
Пример запроса на перенаправление IP-адреса локальной точки будет выглядеть следующим образом:
https://accounts.google.com/o/oauth2/v2/auth?
redirect_uri=http://localhost:3000&
response_type=code&
scope=<SCOPES>&
state=<STATE>&
client_id=<CLIENT_ID>

Проверьте исходящий сетевой вызов.

Метод проверки сетевых вызовов будет различаться в зависимости от типа клиентского приложения.
При анализе сетевых вызовов найдите запросы, отправленные на конечные точки авторизации Google OAuth, и определите, имеет ли параметр redirect_uri какое-либо из следующих значений:
  • redirect_uri=http://127.0.0.1: <port> например redirect_uri=http://127.0.0.1: 3000
  • redirect_uri=http://[::1]: <port> например redirect_uri=http://[::1]: 3000
  • redirect_uri=http://localhost: <port> например, redirect_uri=http://localhost: 3000
Пример запроса на перенаправление IP-адреса локальной точки будет выглядеть следующим образом:
https://accounts.google.com/o/oauth2/v2/auth?
redirect_uri=http://localhost:3000&
response_type=code&
scope=<SCOPES>&
state=<STATE>&
client_id=<CLIENT_ID>

Перейдите на поддерживаемую альтернативу.

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

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

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

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

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

Доступ со стороны клиента

В следующем примере показано, как получить доступ к API Google на стороне клиента на Android, используя рекомендуемую библиотеку Google Identity Services для Android.

  List 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 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 ), либо используя авторизатор fetcher ( GTMFetcherAuthorizationProtocol ) с клиентской библиотекой Google APIs для Objective-C for 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

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

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

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

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


  // the example below 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)
    });
   });
 });
};

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