Руководство по переходу с метода замыкания IP-адреса на себя

Обзор

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

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

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

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

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

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

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

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

Процесс переноса состоит из двух основных этапов:

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

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

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

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

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

Если вы используете поток замыкания 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 и обрабатывает все вызовы конечных точек авторизации OAuth 2.0.

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

Доступ к 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 <var>ACCESS_TOKEN</var>) или используя авторизатор средства извлечения (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

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

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

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.