OAuth 2.0 彻底改变了身份委托。它主要负责解决访问委托的问题。
假设您希望第三方应用程序读取您的 Facebook 状态消息。您想要授予第三方应用程序访问您的 Facebook 墙的权限。为此,您可以与第三方应用程序共享您的 Facebook 凭据,以便它可以直接访问您的 Facebook 墙。在这种情况下,访问由凭据共享委托。即使这解决了访问委托问题,第三方应用程序也可以使用您的 Facebook 凭据做它想做的事,这反过来又会产生更多问题!
使用 OAuth 2.0,您不必与第三方应用程序共享您的凭据,而只需共享一个仅适用于已定义功能的有时限的临时令牌。
OAuth 2.0 参与者
在典型的 OAuth 流程中,有四个参与者。
- 资源所有者 —资源的所有者。根据前面的用例,资源所有者是拥有 Facebook 的 Facebook 用户。
- 资源服务器 —受保护的资源托管在这里。如上述场景所示,托管 Facebook API 的服务器是资源服务器。
- 客户端 —这是想要代表其所有者访问资源的应用程序。上述用例中的客户端是第三方 Web 应用程序。
- 授权服务器 —作为安全令牌服务,它向客户端应用程序颁发 OAuth 2.0 访问令牌。前面用例中的授权服务器是 Facebook 本身。
资助类型
OAuth 2.0 授权类型定义了客户端如何从资源所有者那里获得授权以代表他们访问资源。OAuth 2.0 将这个明确定义的目的称为范围。客户端应用程序的范围决定了它可以对给定资源执行哪些操作。
OAuth 2.0 核心规范引入了四种核心授权类型。
- 授权码授权类型
- 隐式授权类型
- 资源所有者密码凭证授权类型
- 客户端凭证授权类型
授权码授权类型
通常,推荐用于可以打开网络浏览器的网络或本机移动应用程序。授权代码授予类型由访问客户端应用程序的资源所有者发起。客户端应用程序必须向授权服务器注册。
将用户重定向到授权服务器的授权端点时,客户端应用程序生成以下 HTTP 请求:
https://www.facebook.com/v8.0/dialog/oauth?response_type=code,granted_scopes&client_id=672176943231521&redirect_uri=https://callback_url.com&scope=public_profile,email
OAuth 2.0 授权服务器的授权端点是众所周知的并已发布。Response_type 必须是代码。授权服务器知道该请求是针对授权代码的。client_id 标识客户端应用程序。一旦客户端应用程序向授权服务器注册,它就会收到一个 client_id 和一个 client_secret。客户端注册时,客户端应用必须提供一个受其控制的URL作为redirect_uri,并且在初始请求中,redirect_uri参数必须与向授权服务器注册的匹配。在批准屏幕上,scope 参数向授权服务器指示客户端对目标资源或 API 所需的访问级别。
回调 URI 看起来像这样
https://callback_url.com/?code=AQDpbgl-BQzleWPaxmsNe_z_kkfYiiZrZHOwOCBxS5XdSXRNaK5B9tIoYh8IrAsf7KbsGskUwSrln-Mhr64vV0IBg-ZWX5cO-Le0Ao4NqMkFm6ajXTHTRfP08Deqnxi-hJ35-jqjYxuIdby3JifZ64T3TMEiDx2g46riJ5_3FYKMJf9iFjwFRPL1-1c7X9HxAibr
授权服务器返回的授权代码充当中间代码。此代码将最终用户或资源所有者映射到 OAuth 客户端。OAuth 客户端可以向授权服务器的令牌端点验证自己。在将代码交换为访问令牌之前,授权服务器应验证代码是否已颁发给经过身份验证的 OAuth 客户端。
隐式授权类型
在 Web 浏览器中运行的 JavaScript 客户端通常使用隐式授权来获取访问令牌。对于 JavaScript 客户端,我们不建议使用隐式授权类型,而是建议使用无需客户端身份验证的授权代码授权类型。
注意:切勿在生产部署中使用它。
JavaScript 通过将用户重定向到授权服务器来启动隐式授权流程。Response_type 向授权服务器表明客户端需要令牌,而不是代码。隐式授权类型不需要授权服务器对 JavaScript 客户端进行身份验证;它只需要发送 client_id。请求中redirect_uri是可选的;如果存在,则它必须与客户注册时提供的内容相匹配。
https://authz.server.com/oauth2/authorize?response_type=token&client_id=672176943231521&redirect_uri=https://callback_url.com
返回以下响应。隐式授权类型将访问令牌作为 URI 片段发送,并且不提供刷新机制。
https://callback_url.com/#access_token=33cac93e1d29343535373dbfb460&expires_in=3600
资源所有者密码凭证授权类型
资源所有者必须信任资源所有者密码凭据授予类型下的客户端应用程序。客户端应用程序需要直接来自资源所有者的凭据。
客户端凭证授权类型
此授权类型使客户端成为资源的所有者。授权服务器响应中包含访问令牌。与资源所有者密码凭证授权类型不同,客户端凭证授权类型不返回刷新令牌。
客户端凭证授予类型主要用于没有最终用户参与的系统到系统交互。
刷新授权类型
尽管隐式授权类型和客户端凭据授权类型不带有刷新令牌,但其他两个带有。刷新令牌可用于在不涉及资源所有者的情况下扩展访问令牌的有效性。
选择正确的资助类型
要为这些应用程序选择正确的授权类型,我们必须首先确定客户端应用程序将如何访问 OAuth 安全 API:独立或代表最终用户。当应用程序要自己访问API时,我们应该使用客户端凭证授权类型,但如果不是,我们应该使用授权码授权类型。
隐式和密码授权现在已过时。
OAuth 2.0 令牌类型
OAuth 2.0 不绑定任何令牌类型。如果需要,您可以在 OAuth 2.0 中引入自己的令牌类型。客户端必须了解授权服务器在 OAuth 令牌响应中返回的 token_type。授权服务器可以根据令牌类型向响应添加其他属性/参数。
OAuth 2.0 有两个主要的令牌配置文件:
- OAuth 2.0 不记名令牌配置文件
- OAuth 2.0 MAC 令牌配置文件
如今,几乎所有 OAuth 2.0 部署都基于 OAuth 2.0 Bearer Token Profile。
OAuth 2.0 不记名令牌配置文件
为避免在传输过程中丢失不记名令牌,必须始终通过传输层安全性 (TLS) 发送不记名令牌。客户端从授权服务器获得承载访问令牌后,可以通过三种方式与资源服务器进行通信。
HTTP 授权标头是包含访问令牌的最流行方式。
也可以将访问令牌作为查询参数包含在内。JavaScript 客户端应用程序大多使用这种方法。
访问令牌也可以作为表单编码的正文参数发送。
OAuth 2.0 客户端类型
OAuth 2.0 识别两种类型的客户端:
- 机密客户端—— 客户端能够保护自己的凭据(客户端密钥和客户端机密)。
- 公共客户—公共客户不能
OAuth 2.0 中定义了三种类型的客户端配置文件:
- Web 应用程序 ——Web 应用程序被认为是机密客户端,在 Web 服务器上运行:最终用户或资源所有者通过 Web 浏览器访问此类应用程序。
- 基于用户代理的应用程序 ——使用用户代理的应用程序被视为公共客户端:它们从 Web 服务器下载代码并在用户代理上运行,例如在浏览器中运行的 JavaScript。JavaScript 客户端无法保护他们的凭据——最终用户可以看到任何东西。
- 本机应用程序 ——本机应用程序也被视为公共客户端。最终用户可以控制本机应用程序,因此可以提取其中存储的任何机密数据。示例包括 Android 和 iOS 本机应用程序。