概览
2022 年 2 月 16 日,我们 宣布使用更安全的 OAuth 流程来提高 Google OAuth 互动的安全性。本指南可帮助您了解必要的更改和步骤,以便成功从 OAuth 带外 (OOB) 流程迁移到受支持的替代方案。
这项措施是一项防范措施,可在与 Google 的 OAuth 2.0 授权端点互动期间防范钓鱼式攻击和应用冒充攻击。
什么是 OOB?
OAuth 带外 (OOB) 也称为手动复制/粘贴选项,是一种旧版流程,用于支持在用户请求 OAuth 同意后没有重定向 URI 来接受凭据的原生客户端。OOB 流程会带来远程钓鱼式攻击风险,并且客户端必须迁移到替代方法以防范此漏洞。OOB 流程即将被所有客户端类型(即 Web 应用、Android、iOS、Universal Windows Platform (UWP)、Chrome 应用、电视和受限输入设备、桌面应用)弃用。
重要合规日期
- 2022 年 2 月 28 日 - OOB 流程的新 OAuth 用量被禁用
- 2022 年 9 月 5 日 - 不合规的 OAuth 请求可能会显示面向用户的警告消息
- 2022 年 10 月 3 日 - 2022 年 2 月 28 日之前创建的 OAuth 客户端已废弃 OOB 流程
- 2023 年 1 月 31 日 - 所有现有客户端(包括豁免的客户端)都会被屏蔽
对于不符合政策规定的请求,系统会向用户显示一条错误消息。 该消息会告知用户,该应用在显示您在 Google API 控制台的 OAuth 权限请求页面中注册的支持电子邮件时遭到屏蔽。
- 确定您是否受到影响。
- 如果您受到影响,请迁移到更安全的替代方案。
确定您是否受到影响
此弃用仅适用于正式版应用(即发布状态为 正式版的应用)。对于 测试发布状态的应用,此流程将继续有效。
请在 Google API Console 的 OAuth Consent Screen page中查看发布状态;如果您在发布状态为“正式版”的项目中使用 OOB 流程,请继续执行下一步。
如何确定您的应用是否使用了 OOB 流程
检查您的应用代码或传出的网络调用(如果您的应用使用 OAuth 库)以确定您的应用发出的 Google OAuth 授权请求是否使用了 OOB 重定向 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>
检查传出的网络调用
- Web 应用 - 检查 Chrome 上的网络活动
- Android - 使用 Network Inspector 检查网络流量
-
Chrome 应用
- 导航到 Chrome 扩展程序页面
- 选中扩展程序页面右上角的开发者模式复选框
- 选择要监控的扩展程序
- 在扩展程序页面的检查视图部分中点击后台页面链接
- 系统会打开开发者工具弹出式窗口,您可以在其中通过 “网络”标签页监控网络流量
- iOS - 使用付款方式分析 HTTP 流量
- Universal Windows Platform (UWP) - 在 Visual Studio 中检查网络流量
- 桌面应用 - 针对开发该应用的操作系统 使用网络捕获工具
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 流程使用的是 Android 或 iOS OAuth 客户端类型,则应改用我们的 Google 登录移动 SDK(Android、iOS)。
借助该 SDK,您可以轻松访问 Google API 并处理对 Google OAuth 2.0 授权端点的所有调用。
以下文档链接介绍了如何在不使用 OOB 重定向 URI 的情况下使用 Google 登录 SDK 访问 Google API。
访问 Google API (Android)
服务器端(离线)访问
以下示例展示了如何在 Android 的服务器端访问 Google API。Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data); try { GoogleSignInAccount account = task.getResult(ApiException.class); // request a one-time authorization code that your server exchanges for an // access token and sometimes refresh token String authCode = account.getServerAuthCode(); // Show signed-in UI updateUI(account); // TODO(developer): send code to server and exchange for access/refresh/ID tokens } catch (ApiException e) { Log.w(TAG, "Sign-in failed", e); updateUI(null); }
查看服务器端访问指南,了解如何从服务器端访问 Google API。
在 iOS 应用中访问 Google API
客户端访问
以下示例展示了如何在 iOS 设备上访问客户端 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
) 中添加访问令牌,或者通过
适用于 REST 的 Objective-C 的 Google API 客户端库使用提取工具授权方 (GTMFetcherAuthorizationProtocol
)。
查看客户端访问指南,了解如何在客户端访问 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 应用客户端上使用 OOB 流程,则应改用 Chrome Identity API。
以下示例展示了如何在不使用 OOB 重定向 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 指南,详细了解如何通过 Chrome Identity API 访问身份验证用户并调用 Google 端点。
Web 应用
确定您的应用使用的是 Web 应用的 OOB 流程后,您应迁移到我们的某个 Google API 客户端库。此处列出了适用于不同编程语言的客户端库。
借助这些库,您可以轻松访问 Google API 并处理对 Google 端点的所有调用。
服务器端(离线)访问
- 站立服务器并定义一个可公开访问的端点(重定向 URI)来接收授权代码。
- 在 Google API Console的 Credentials page 中配置 重定向 URI
以下代码段展示了一个 NodeJS 示例,展示如何使用 Google Drive API 在服务器端列出用户的 Google 云端硬盘文件,而无需使用 OOB 重定向 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. }); } } }
查看 服务器端 Web 应用指南,了解如何从服务器端访问 Google API。
客户端访问
下面的代码段(使用 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(...); }
请参阅 客户端 Web 应用指南,了解如何从客户端访问 Google API。
桌面客户端
如果您认为您的应用在桌面客户端上使用 OOB 流程,则应改用
环回 IP 地址(localhost
或 127.0.0.1
)流程。