概览
2022 年 2 月 16 日,我们 宣布,计划通过使用更安全的 OAuth 流程,提高 Google OAuth 互动安全性。本指南可帮助您了解从环回 IP 地址流程成功迁移到受支持的替代方案所需的更改和步骤。
此举措是一项保护措施,旨在防范在与 Google 的 OAuth 2.0 授权端点互动期间发生的钓鱼式攻击和应用假冒攻击。
什么是环回 IP 地址流程?
环回 IP 地址流程支持使用环回 IP 地址或localhost
作为重定向 URI 的主机组件,在用户批准 OAuth 意见征求请求后,系统会将凭据发送到该主机组件。此流程容易受到中间人攻击,在这种攻击中,恶意应用在某些操作系统上访问同一环回接口,可能会拦截授权服务器对给定重定向 URI 的响应,并获得对授权代码的访问权限。
环回 IP 地址流程将针对原生 iOS、Android 和 Chrome OAuth 客户端类型被弃用,但桌面应用仍将继续支持该流程。
重要合规日期
- 2022 年 3 月 14 日 - 禁止新的 OAuth 客户端使用环回 IP 地址流程
- 2022 年 8 月 1 日 - 系统可能会向不合规的 OAuth 请求显示面向用户的警告消息
- 2022 年 8 月 31 日 - 系统会屏蔽 2022 年 3 月 14 日之前创建的原生 Android、Chrome 应用和 iOS OAuth 客户端的环回 IP 地址流程
- 2022 年 10 月 21 日 - 所有现有客户均被屏蔽(包括豁免的客户)
对于不合规的请求,系统会显示面向用户的错误消息。 该消息会告知用户应用已被屏蔽,同时显示您在 Google API 控制台的 OAuth 权限请求页面中注册的支持电子邮件地址。
- 确定您是否受到影响。
- 如果您受到影响,请改用受支持的替代方案。
确定您是否受到影响
查看您的 OAuth 客户端 ID 类型
前往 的 ,然后在 OAuth 2.0 客户端 ID 部分下查看您的 OAuth 客户端 ID 类型。它可以是以下任一平台:Web 应用、Android、iOS、通用 Windows 平台 (UWP)、Chrome 应用、电视和有限输入设备、桌面应用。
如果您的客户端类型为 Android、Chrome 应用或 iOS,并且您使用的是环回 IP 地址流程,请继续执行下一步。
如果您在桌面应用 OAuth 客户端上使用环回 IP 地址流程,则无需执行与此弃用相关的任何操作,因为我们将继续支持使用该 OAuth 客户端类型。
如何确定您的应用是否使用了环回 IP 地址流
检查您的应用代码或出站网络调用(如果您的应用使用 OAuth 库),以确定您的应用发出的 Google OAuth 授权请求是否使用了环回重定向 URI 值。
检查应用代码
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
https://accounts.google.com/o/oauth2/v2/auth? redirect_uri=http://localhost:3000& response_type=code& scope=<SCOPES>& state=<STATE>& client_id=<CLIENT_ID>
检查传出网络调用
- 网络应用 - 检查 Chrome 中的网络活动
- Android - 使用网络检查器检查网络流量
-
Chrome 应用
- 前往 Chrome 扩展程序页面
- 选中扩展程序页面右上角的开发者模式复选框
- 选择要监控的扩展程序
- 点击扩展程序页面检查视图部分中的后台页面链接
- 系统随即会打开一个 Developer Tools(开发者工具)弹出式窗口,您可以在 “Network”标签页中监控网络流量
- iOS - 使用 Instruments 分析 HTTP 流量
- 通用 Windows 平台 (UWP) - 在 Visual Studio 中检查网络流量
- 桌面应用 - 使用适用于应用开发所用操作系统的网络捕获工具
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
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)
如果您确定您的应用使用的是 Android 或 iOS OAuth 客户端类型的环回 IP 地址流程,则应改用推荐的 SDK (Android、iOS)。
借助该 SDK,您可以轻松访问 Google API,并处理对 Google 的 OAuth 2.0 授权端点的所有调用。
以下文档链接提供了有关如何使用推荐的 SDK 访问 Google API 而无需使用环回 IP 地址重定向 URI 的信息。
在 Android 上访问 Google API
客户端访问
以下示例展示了如何使用推荐的 Google Identity 服务 Android 库在 Android 客户端上访问 Google API。
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()
方法。
服务器端(离线)访问
以下示例展示了如何在 Android 服务器端访问 Google API。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()
方法,该方法会返回授权代码,您可以将该代码发送到后端以获取访问令牌和刷新令牌。
在 iOS 应用中访问 Google API
客户端访问
以下示例展示了如何在 iOS 客户端上访问 Google API。
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
) 与
适用于 REST 的 Objective-C 的 Google API 客户端库搭配使用。
请参阅客户端访问指南,了解如何在客户端访问 Google API。 了解如何在客户端访问 Google API。
服务器端(离线)访问
以下示例展示了如何在服务器端访问 Google API 以支持 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 }
查看服务器端访问指南,了解如何从服务器端访问 Google API。
Chrome 应用客户端
如果您确定您的应用在 Chrome 应用客户端上使用环回 IP 地址流程,则应改用 Chrome Identity API。
以下示例展示了如何在不使用环回 IP 地址重定向 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) }); }); }); };
如需详细了解如何使用 Chrome Identity API 访问经过身份验证的用户并调用 Google 端点,请参阅 Chrome Identity API 指南。