从0开始构建一个Oauth2Server服务 25
Native App 使用OAuth
为本机应用程序支持 OAuth 时要牢记的一些特殊注意事项。与基于浏览器的应用程序一样,本机应用程序不能使用客户端机密,因为这将要求开发人员在应用程序的二进制分发中传送机密。事实证明,反编译和提取秘密相对容易。因此,本机应用程序必须使用不需要预注册客户端密码的 OAuth 流程。
当前的行业最佳实践是使用授权流程和 PKCE 扩展,从请求中省略客户端密码,并使用外部用户代理来完成流程。外部用户代理通常是设备的本机浏览器(具有与本机应用程序不同的安全域),因此应用程序无法访问 cookie 存储或检查或修改浏览器内的页面内容。由于在这种情况下应用程序无法访问正在使用的浏览器内部,这为设备提供了在授权不同应用程序时保持用户登录状态的机会,这样他们就不必在每次授权新应用程序时都输入其凭据应用。
近年来,iOS 和 Android 一直致力于通过提供可从应用程序内部启动的本机用户代理来进一步改善本机应用程序的 OAuth 用户体验,同时仍与启动它的应用程序隔离。结果是用户不再需要离开应用程序来启动共享系统 cookie 的本机浏览器。这首先是SFSafariViewController
在 iOS 9 中添加的,后来SFAuthenticationSession
在 iOS 11 和ASWebAuthenticationSession
iOS 12 中得到了发展。
使用系统浏览器
将 OAuth 界面嵌入到应用内的 Web 视图中曾经是原生应用的常见做法。这种方法存在多个问题,包括客户端应用程序可能会窃听用户在登录时输入其凭据,甚至会出现虚假的授权页面。移动操作系统安全性通常以嵌入式 Web 视图不与系统的本机浏览器共享 cookie 的方式实现,因此用户的体验更差,因为他们每次都需要输入他们的凭据。
完成授权流程的更安全和可信的方法是启动系统浏览器。然而,在添加专门的设备 API 之前,这有一个缺点,即用户被弹出应用程序并启动他们的浏览器,然后重定向回应用程序,这也不是理想的用户体验。
值得庆幸的是,移动平台一直在解决这个问题。现在在 iOS 和 Android 上有可用的 API,应用程序可以启动系统浏览器但停留在应用程序的上下文中。API 不允许客户端应用程序窥视浏览器内部,从而获得使用外部浏览器的安全优势以及始终留在应用程序中的用户体验优势。
强烈鼓励本机应用程序开发人员使用这些特殊用途的 API,但如果他们由于某种原因不能使用,请回退到启动外部浏览器而不是嵌入式 Web 视图。
授权服务器应通过尝试检测授权 URL 是否在嵌入式 Web 视图中启动并拒绝请求来强制执行此行为。用于检测页面是在嵌入式 Web 视图中访问还是在系统浏览器中访问的特定技术将取决于平台,但通常涉及检查用户代理标头。
本机应用程序的重定向 URL
为了支持多种类型的本机应用程序,您的服务器将需要支持注册三种类型的重定向 URL,每种都支持略有不同的用例。
HTTPS 网址匹配
iOS 和 Android 都允许应用程序注册 URL 模式,这些模式指示应用程序应该在系统浏览器访问与注册模式匹配的 URL 时启动。这通常被应用程序用于“深层链接”到本机应用程序,例如当在浏览器中查看 Yelp URL 时,Yelp 应用程序打开餐厅页面。
应用程序也可以使用此技术来注册 URL 模式,该模式将在授权服务器重定向回应用程序时启动应用程序。如果平台提供此功能,则这是本机应用程序的推荐选择,因为这提供了应用程序属于它匹配的 URL 的最大完整性。在平台不支持应用程序声明的 URL 的情况下,这也提供了合理的回退。
自定义 URL 方案
某些平台允许应用程序注册自定义 URL 方案,只要在浏览器或其他应用程序中打开具有该方案的 URL,该方案就会启动应用程序。支持带有自定义 URL 方案的重定向 URL 允许客户端启动外部浏览器以完成授权流程,然后在授权完成后重定向回应用程序。然而,这种方法不如 HTTPS URL 匹配方法安全,因为没有自定义 URL 方案的全局注册来避免开发人员之间的冲突。
应用程序开发人员应该选择一种 URL 方案,该方案可能是全球唯一的,并且他们可以断言对其进行控制。由于操作系统通常没有关于特定应用程序是否声明了 URL 方案的注册表,因此理论上两个应用程序可以独立选择相同的方案,例如myapp://
. 如果您想帮助防止应用程序开发人员使用自定义方案发生冲突,您应该建议(甚至强制)他们使用一种方案,该方案是他们控制的域的反向域名模式。至少,您可以要求重定向 URL 至少包含一个,.
以免与其他系统方案(例如mailto
或 )冲突ftp
。
例如,如果一个应用程序有一个名为 的对应网站photoprintr.example.org
,则可以用作其 URL 方案的反向域名将是org.example.photoprintr
。开发人员注册的重定向 URL 将以org.example.photoprintr://
. 通过强制执行此操作,您可以帮助鼓励开发人员选择不会与其他已安装应用程序冲突的显式 URL 方案。
使用自定义 URL 方案的应用程序将正常启动授权请求,如授权请求中所述,但将提供具有其自定义 URL 方案的重定向 URL。授权服务器仍应验证此 URL 之前是否已注册为允许的重定向 URL,并且可以像 Web 应用程序注册的任何其他重定向 URL 一样对待它。
当授权服务器将本机应用程序重定向到具有自定义方案的 URL 时,操作系统将启动该应用程序并使整个重定向 URL 可供原始应用程序访问。该应用程序可以像普通的 OAuth 2.0 客户端一样提取授权代码。
Loopback URLs
本机应用程序可用于支持无缝重定向的另一种技术是在环回接口的随机端口上打开一个新的 HTTP 服务器。这通常只在桌面操作系统或命令行应用程序上完成,因为移动操作系统通常不向应用程序开发人员提供此功能。
这种方法适用于命令行应用程序和桌面 GUI 应用程序。该应用程序将启动 HTTP 服务器,然后开始授权请求,将重定向 URL 设置为环回地址,例如http://127.0.0.1:49152/redirect
并启动浏览器。当授权服务器将浏览器重定向回环回地址时,应用程序可以从请求中获取授权代码。
为了支持这个用例,授权服务器必须支持注册以http://127.0.0.1:[port]/
and http://::1:[port]/
, and开头的重定向 URL http://localhost:[port]/
。授权服务器应该允许任意路径组件以及任意端口号。请注意,在这种情况下,使用 HTTP 方案而不是 HTTPS 是可以接受的,因为请求永远不会离开设备。
登记
与服务器端应用程序一样,本机应用程序还必须向授权服务器注册其重定向 URL。这意味着除了服务器端应用程序的传统 HTTPS URL 之外,授权服务器还需要允许匹配上述所有模式的已注册重定向 URL。
当在授权服务器发起授权请求时,服务器将验证所有请求参数,包括给定的重定向 URL。授权应拒绝请求中无法识别的 URL,以帮助避免授权代码拦截攻击。
PKCE 扩展
由于本机平台上的重定向 URL 的强制执行能力有限,因此还有另一种获得额外安全性的技术,称为代码交换证明密钥,简称 PKCE,发音为“pixie”。
此技术涉及本机应用程序创建一个初始随机秘密,并在将授权代码交换为访问令牌时再次使用该秘密。这样,如果其他应用程序拦截了授权码,则没有原始密码将无法使用。
请注意,PKCE 不会阻止应用程序模拟,它只会阻止授权代码被不同于启动流程的应用程序使用。