从0开始构建一个Oauth2Server服务 17
回调地址 Redirect URL
重定向 URL 是 OAuth 流程的关键部分。用户授权应用成功后,授权服务器会将用户重定向回应用。由于重定向 URL 将包含敏感信息,因此服务不会将用户重定向到任意位置至关重要。
确保用户只会被重定向到适当位置的最佳方法是要求开发人员在创建应用程序时注册一个或多个重定向 URL。在这些部分中,我们将介绍如何处理移动应用程序的重定向 URL、如何验证重定向 URL 以及如何处理错误。
注册RedirectURL
为了避免将用户暴露于开放式重定向器攻击,您必须要求开发人员为应用程序注册一个或多个重定向 URL。授权服务器绝不能重定向到任何其他位置。注册新应用程序包括创建注册表单以允许开发人员为其应用程序注册重定向 URL。
如果攻击者可以在用户到达授权服务器之前操纵重定向 URL,他们可能会导致服务器将用户重定向到恶意服务器,该服务器会将授权代码发送给攻击者。这是攻击者可以尝试拦截 OAuth 交换并窃取访问令牌的一种方式。如果授权端点不限制它将重定向到的 URL,那么它被认为是“开放重定向器”,并且可以与其他东西结合使用以发起与 OAuth 不一定相关的攻击。
有效的重定向 URL
当您构建表单以允许开发人员注册重定向 URL 时,您应该对他们输入的 URL 进行一些基本验证。
已注册的重定向 URL 可以包含查询字符串参数,但片段中不得包含任何内容。如果开发人员尝试注册包含片段的重定向 URL,注册服务器应拒绝该请求。
请注意,对于本机和移动应用程序,该平台可能允许开发人员注册一个 URL 方案,例如myapp://
可以在重定向 URL 中使用的方案。这意味着授权服务器应允许注册任意 URL 方案,以支持为本机应用程序注册重定向 URL。有关详细信息,请参阅移动和本机应用程序。
按请求定制
通常,开发人员会认为他们需要能够在每个授权请求上使用不同的重定向 URL,并且会尝试更改每个请求的查询字符串参数。这不是重定向 URL 的预期用途,授权服务器不应允许。服务器应拒绝任何重定向 URL 与已注册 URL 不完全匹配的授权请求。
如果客户端希望在重定向 URL 中包含特定于请求的数据,它可以改为使用“state”参数来存储将在用户重定向后包含的数据。它既可以在状态参数本身中对数据进行编码,也可以使用状态参数作为会话 ID 将状态存储在服务器上。
Redirect URLs for Native Apps
Native Apps是安装在设备上的客户端,例如桌面应用程序或本机移动应用程序。在支持与安全性和用户体验相关的本机应用程序时,需要牢记一些事项。
授权端点通常会将用户重定向回客户端注册的重定向 URL。根据平台的不同,本机应用程序可以声明一个 URL 模式,或者注册一个将启动应用程序的自定义 URL 方案。例如,一个 iOS 应用程序可以注册一个自定义协议myapp://
,然后使用一个 redirect_uri myapp://callback
。
应用声明的 https URL 重定向
某些平台(Android 和 iOS 9 之后的 iOS)允许应用程序覆盖特定的 URL 模式以启动本机应用程序而不是 Web 浏览器。例如,应用程序可以注册https://app.example.com/auth
,并且每当 Web 浏览器尝试重定向到该 URL 时,操作系统都会启动本机应用程序。
如果操作系统不支持声明 URL,则应使用此方法。如果操作系统对开发人员可以控制此 Web URL 进行某种级别的验证,则这允许操作系统保证本机应用程序的身份。如果操作系统不支持此功能,则应用程序将不得不改用自定义 URL 架构。
自定义 URL 方案
大多数移动和桌面操作系统都允许应用程序注册自定义 URL 方案,当从系统浏览器访问具有该方案的 URL 时,该方案将启动应用程序。
使用此方法,本机应用程序通过使用标准授权代码参数启动系统浏览器来正常启动 OAuth 流程。唯一的区别是重定向 URL 将是带有应用程序自定义方案的 URL。
当授权服务器发送Location
要将用户重定向到的标头myapp://callback#token=....
时,手机将启动应用程序,应用程序将能够恢复授权过程,从 URL 解析访问令牌并将其存储在内部。
自定义 URL 方案命名空间
由于没有集中注册 URL schemes 的方法,应用程序必须尽力选择不会相互冲突的 URL schemes。
您的服务可以通过要求 URL 方案遵循特定模式来提供帮助,并且只允许开发人员注册与该模式匹配的自定义方案。
例如,Facebook 会根据应用程序的客户端 ID 为每个应用程序生成一个 URL 方案。例如,fb00000000://
数字对应于应用程序的客户端 ID。这提供了一种生成全局唯一 URL 方案的相当可靠的方法,因为其他应用不太可能使用具有此模式的 URL 方案。
应用程序的另一种选择是将反向域名模式与受应用程序发布者控制的域一起使用,从而生成例如 URL 方案com.example.myapp
。如果您愿意,这也是服务可以强制执行的内容。
验证 RedirectURL
在三种情况下您需要验证重定向 URL。
- 当开发人员将重定向 URL 注册为创建应用程序的一部分时
- 在授权请求中(授权代码和隐式授权类型)
- 当应用程序为访问令牌交换授权代码时
重定向 URL 注册
正如创建应用程序中所讨论的那样,该服务应该允许开发人员在创建应用程序时注册一个或多个重定向 URL。重定向 URL 的唯一限制是它不能包含片段组件。该服务必须允许开发人员使用自定义 URL 方案注册重定向 URL,以支持某些平台上的本机应用程序。
授权请求
当应用程序启动 OAuth 流程时,它将把用户定向到您服务的授权端点。该请求将在 URL 中包含多个参数,包括重定向 URL。
此时,授权服务器必须验证重定向 URL 以确保请求中的 URL 与应用程序的注册 URL 之一相匹配。该请求还将有一个client_id
参数,因此服务应根据该参数查找重定向 URL。攻击者完全有可能使用一个应用程序的客户端 ID 和攻击者的重定向 URL 来制作授权请求,这就是需要注册的原因。
该服务应查找 URL 的精确匹配,并避免仅匹配特定 URL 的一部分。(如果客户端需要自定义每个请求,可以使用 state 参数。)简单的字符串匹配就足够了,因为不能为每个请求自定义重定向 URL。服务器需要做的就是检查请求中的重定向 URL 是否与开发人员在注册其应用程序时输入的重定向 URL 之一相匹配。
如果重定向 URL 不是已注册的重定向 URL 之一,则服务器必须立即显示错误指示,并且不会重定向用户。这避免了将您的授权服务器用作开放重定向器。
授予访问令牌
令牌端点将收到一个请求,用授权代码交换访问令牌。此请求将包含重定向 URL 以及授权代码。作为一项额外的安全措施,服务器应验证此请求中的重定向 URL 是否与包含在此授权代码的初始授权请求中的重定向 URL 完全匹配。如果重定向 URL 不匹配,服务器将拒绝请求并报错。