Обзор
16 февраля 2022 года мы объявили о планах сделать взаимодействие с Google OAuth более безопасным за счет использования более защищенных потоков OAuth. Это руководство поможет вам понять необходимые изменения и шаги для успешного перехода от внеполосного (OOB) потока OAuth к поддерживаемым альтернативам.
Эти меры направлены на защиту от фишинговых атак и атак с использованием поддельных приложений при взаимодействии с точками авторизации Google OAuth 2.0.
Что такое OOB?
Внеполосная авторизация OAuth (OOB) , также известная как ручное копирование/вставка, — это устаревший процесс, разработанный для поддержки нативных клиентов, у которых отсутствует URI перенаправления для приема учетных данных после того, как пользователь подтвердит запрос на согласие OAuth. Внеполосная авторизация представляет собой риск удаленного фишинга, и клиентам необходимо перейти на альтернативный метод для защиты от этой уязвимости.Использование стандартного потока обработки данных прекращается для всех типов клиентов, включая веб-приложения, Android, iOS, универсальную платформу Windows (UWP), приложения Chrome, телевизоры и устройства с ограниченным набором входных данных, а также настольные приложения.
Ключевые сроки соблюдения требований
- 28 февраля 2022 г. — блокируется новое использование OAuth для потока OOB.
- 5 сентября 2022 г. — при запросах OAuth, не соответствующих требованиям, может отображаться предупреждающее сообщение для пользователя.
- 3 октября 2022 г. — стандартный процесс аутентификации (OOB) устарел для клиентов OAuth, созданных до 28 февраля 2022 г.
- 31 января 2023 г. - все существующие клиенты заблокированы (включая клиентов, на которых распространяется исключение).
При несоответствии запросам пользователю будет отображаться сообщение об ошибке. В сообщении будет указано, что приложение заблокировано, при этом будет отображаться адрес электронной почты службы поддержки, указанный в настройках согласия OAuth в консоли Google API .
- Определите, затрагивает ли это вас.
- Если вас это затронуло, перейдите на более безопасный вариант.
Определите, затрагивает ли это вас.
Данное предупреждение относится только к приложениям, находящимся в производственной среде (т. е. приложениям со статусом публикации « В производственной среде» ). Процесс будет продолжать работать для приложений со статусом публикации «Тестирование» .
Проверьте статус публикации на странице «Брендирование OAuth» в консоли Google Cloud и перейдите к следующему шагу, если вы используете стандартный процесс в проекте со статусом публикации «В производстве».
Как определить, использует ли ваше приложение стандартный поток обработки данных (OOB flow)
Проверьте код вашего приложения или исходящий сетевой вызов (если ваше приложение использует библиотеку OAuth), чтобы определить, использует ли запрос авторизации Google OAuth, который отправляет ваше приложение, значение URI перенаправления, недопустимое в исходном коде.
Проверьте код вашего приложения.
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>
Проверьте исходящий сетевой вызов.
- Веб-приложение — проверка сетевой активности в Chrome
- Android — проверка сетевого трафика с помощью Network Inspector
- Приложения Chrome
- Перейдите на страницу расширений Chrome.
- Установите флажок «Режим разработчика» в правом верхнем углу страницы расширения.
- Выберите расширение, которое хотите отслеживать.
- В разделе «Просмотреть элементы интерфейса» на странице расширения нажмите на ссылку «Фоновая страница ».
- Откроется всплывающее окно «Инструменты разработчика» , где вы сможете отслеживать сетевой трафик на вкладке «Сеть».
- iOS — анализ HTTP-трафика с помощью Instruments
- Для настольных приложений используйте инструмент захвата сетевого трафика, доступный для операционной системы, для которой было разработано приложение.
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 и обрабатывает все вызовы к конечным точкам авторизации Google OAuth 2.0.
Приведенные ниже ссылки на документацию содержат информацию о том, как использовать рекомендуемые SDK для доступа к API Google без использования стандартного URI перенаправления.
Доступ к API Google на Android
Доступ со стороны клиента
В следующем примере показано, как получить доступ к API Google на стороне клиента на Android, используя рекомендуемую библиотеку Google Identity Services для Android.
ListrequestedScopes = 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.ListrequestedScopes = 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
Если вы обнаружите, что ваше приложение использует стандартный поток обработки данных в клиентском приложении Chrome, вам следует перейти на использование API Chrome Identity .
В приведенном ниже примере показано, как получить все контакты пользователей без использования стандартного URI перенаправления.
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, ознакомьтесь с руководством .
Веб-приложение
Если вы обнаружите, что ваше приложение использует стандартный поток обработки данных для веб-приложений, вам следует перейти на использование одной из наших клиентских библиотек Google API. Клиентские библиотеки для различных языков программирования перечислены здесь .
Эти библиотеки упрощают доступ к API Google и обработку всех вызовов к конечным точкам Google.
Доступ со стороны сервера (в автономном режиме)
- Создайте сервер и определите общедоступную конечную точку (URI перенаправления) для получения кода авторизации.
- Настройте URI перенаправления на странице «Клиенты» в консоли Google Cloud.
Приведённый ниже фрагмент кода демонстрирует пример использования API Google Drive на NodeJS для отображения списка файлов пользователя в Google Drive на стороне сервера без использования стандартного URI перенаправления.
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 демонстрирует пример использования API Google для доступа к событиям календаря пользователя на стороне клиента.
// 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 ) .