OAuth 2.0 身份认证模式
场景
用户小明将照片存储在云端的照片服务器上,他想要授权一个第三方打印服务,来访问他存储在服务器上的照片进行打印。
在传统的客户端服务器身份验证模式
打印服务(客户端)向照片服务器(服务器)通过小明的账号密码请求小明的照片。在这个过程中,为了让打印服务能够访问到自己存在照片服务器的照片,用户小明必须向打印服务提供自己的照片服务器的账号密码。
这整个流程存在一些问题和限制:
- 第三方应用程序(上例中的打印服务)必须要存储终端用户(小明)的凭证(账号/密码),通常是明文的账号密码。
- 服务器(上例中的照片资源服务器)必须要支持账号密码认证,尽管账号密码认证的固有安全性脆弱的问题。
- 第三方应用(上例中的打印服务)获得对资源所有者(小明)受保护资源(照片)的过于广泛的访问,即小明可能只想打印他存在照片服务器上的某一张照片,但是通过这种模式,打印服务实际上可以访问到小明在照片资源服务器上的所有照片。而且在这个过程小明无法指定打印服务访问照片的范围和规定访问时间。
- 资源所有者(小明)不能撤销对单个第三方的访问,而不撤销对所有第三方的访问权限,并且必须通过更改第三方的密码来撤销访问权限。如打印服务、上传服务都通过小明的账号密码访问到照片服务器时,小明无法对打印服务单独撤销访问照片服务器的授权,而且撤销授权的方式只能通过更改照片服务器密码的方式。
- 任何第三方应用程序的泄露都会导致最终用户密码和该密码保护的所有数据的泄露。
OAuth 2.0 身份验证模式
同样的场景下,OAuth 通过引入了认证授权服务并且通过将客户端(打印服务)与资源所有者(小明)的角色进行区分来解决了上述问题。在 OAuth 模式下,客户端(打印服务)请求资源(照片)由资源所有者控制(小明)由资源服务器(照片服务器)托管,这种模式解决了客户端(打印服务)通过认证服务器颁发的访问令牌来访问资源服务器(照片服务器),而不是资源所有者的账号密码(小明)。
OAuth2.0 概念
OAuth 2.0 角色
OAuth 定义了 4 个角色。
-
资源拥有者(resource owner):能够授予对受保护资源的访问权限的实体。当资源所有者是一个人时,它称为终端用户。
-
资源服务器(resource server ):托管受保护资源的服务器,能够使用访问令牌接受和响应受保护资源的请求。
-
客户端(client):代表资源所有者及其授权发出受保护资源请求的应用程序。术语“客户端”并不意味着任何特定的实现特征(例如,应用程序是否在服务器,台式机或其他设备上执行)。
-
授权服务器(authoritation server):成功验证资源所有者并获得授权后,服务器会向客户端发布访问令牌。
OAuth 2.0 协议流程
图中所示的抽象 OAuth 2.0 流程描述了四个角色之间的交互,并包括以下步骤:
(A). 客户端请求资源所有者的授权。可以直接向资源所有者发出授权请求(如图所示),或者最好是通过授权服务器作为中介间接进行授权。
(B). 客户收到授权,这是代表资源所有者授权的凭证,使用本规范中定义的四种授权类型之一或扩展授权类型来表示。授权授予类型取决于客户端请求授权所使用的方法以及授权服务器支持的类型。
(C). 客户端通过向授权服务器进行身份验证并提供授权来请求访问令牌。
(D). 授权服务器对客户端进行身份验证并验证授权,如果有效,则颁发访问令牌。
(E). 客户端从资源服务器请求受保护的资源,并通过提供访问令牌来进行身份验证。
(F). 资源服务器验证访问令牌,如果有效,则处理该请求。
OAuth 2.0 四种授权模式(Authorization Grant)
授权授予是一种凭证,它表示客户端用于获取访问令牌的资源所有者的授权(用于访问其受保护的资源)。OAuth 2.0 定义了四种授权授予的类型,授权码 (authorization code), 简洁授权码(Implicit),资源所有者密码凭证(resource owner paasword) 和客户端密码凭证(client credentials) —— 以及用于定义其他类型的可扩展扩展机制。
授权码模式(Authorization Code)
通过使用授权服务器作为客户端和资源所有者之间的中介,可以获取授权代码。从而取代掉直接向资源服务器获取授权。客户端不是直接从资源所有者请求授权,而是将资源所有者定向到授权服务器(通过[RFC2616]中定义的用户代理),该服务器进而将资源所有者与授权代码一起引导回客户端。
在使用授权码将资源所有者引导回客户端之前,授权服务器对资源所有者进行身份验证并获得授权。由于资源所有者仅通过授权服务器进行身份验证,因此永远不会与客户端共享资源所有者的凭据。
授权代码提供了一些重要的安全益处,例如对客户端进行身份验证的能力,以及将访问令牌直接传输到客户端的过程,而无需将其传递给资源所有者的用户代理并将其暴露给其他人,包括资源所有者。
隐式授予(Implict)
隐式授予是针对使用脚本语言(如 JavaScript)在浏览器中实施的客户端优化的简化授权代码流。在隐式授予的流程中,在隐性流程中,客户直接获得访问令牌(由资源所有者授权),而不是向客户发出授权码。授予类型是隐含的,因为未颁发中间凭据(如授权代码)(后来用于获取访问令牌)。
在隐性授予流程期间发出访问令牌时,授权服务器不会对客户端进行身份验证。在某些情况下,可以通过用于向客户端传递访问令牌的 URI 重定向来验证客户身份。访问令牌可能会接触资源所有者或其他应用程序,并访问资源所有者的用户代理。
隐式授予提高了某些客户(例如作为浏览器内应用程序实施的客户)的响应能力和效率,因为它减少了获得访问令牌所需的往返次数。然而,这种便利性应与使用隐式授予的安全影响进行权衡,尤其在授权码授予模式可用的情况下。
资源所有者的密码凭证(Resource Owner Password Credentials)
资源所有者密码凭据(即用户名和密码)可直接用作授权授予,以获取访问令牌。只有在资源所有者和客户之间有高度信任时,才应使用凭据(例如,客户端是设备操作系统的一部分或高度特权的应用程序),并且当其他授权授予模式是不可用的情况下(如授权码模式)。
尽管此授予类型需要直接访问资源所有者凭据的客户端,但资源所有者凭据用于单个请求,并交换为访问令牌。此授予类型可以通过将凭据与长期访问令牌或刷新令牌交换来消除客户端存储资源所有者凭据以供将来使用所需的需求。
客户端的密码凭证(Client Credentials)
当授权范围仅限于客户端控制下的受保护资源或以前与授权服务器安排的受保护资源时,客户凭据(或其他形式的客户身份验证)可用作授权授予。客户凭据通常用作授权授予,通常当客户代表其自身(客户端也是资源所有者)或根据之前与授权服务器安排的授权请求访问受保护资源时。
访问令牌(Access Token)
访问令牌是用于访问受保护资源的凭据。访问令牌是代表向客户发出的授权的字符串。令牌表示特定的访问范围和期限,由资源所有者授予,由资源服务器和授权服务器强制执行。
令牌可能表示用于检索授权信息的标识符,也可以以可验证的方式(即由某些数据和签名组成的令牌字符串)自行包含授权信息。可能需要超出此规范范围的其他身份验证凭据,以便客户端使用令牌。
访问令牌提供了一个抽象层,用资源服务器理解的单个令牌替换不同的授权构造(例如用户名和密码)。这种抽象使签发访问令牌的权限性比用于获取访问令牌的授权授予更具限制性,并消除了资源服务器理解各种身份验证方法的需要。
访问令牌可以根据资源服务器安全要求具有不同的格式、结构和使用方法(例如加密属性)。
刷新令牌(Refresh Token)
刷新令牌是用于获取访问令牌的凭据。刷新令牌由授权服务器向客户端发出,用于在当前访问令牌失效或过期时获得新的访问令牌,或获得相同或更窄范围的其他访问令牌(访问令牌的使用寿命可能比资源所有者授权的要短,权限更少)。签发刷新令牌可由授权服务器自行决定。如果授权服务器发出刷新令牌,则在发布访问令牌时包括它。
刷新令牌是代表资源所有者授予客户端的授权的字符串。字符串通常对客户端不透明。令牌表示用于存储授权信息。与访问令牌不同,刷新令牌仅用于授权服务器,且从未发送到资源服务器。
刷新过期 token 流程如下:
(A) 客户端请求通过使用授权服务器进行身份验证并提交授权授予书来访问令牌。
(B) 授权服务器对客户端进行身份验证,并验证授权授予,如果有效,则发出访问令牌和刷新令牌。
(C) 客户端通过提交访问令牌向资源服务器提出受保护的资源请求。
(D) 资源服务器验证访问令牌,如果有效,则服务于请求。
(E) 步骤(C)和(D)重复,直到访问令牌过期。如果客户端知道访问令牌过期,则会跳到步骤(G):否则,它还会提出另一个受保护的资源请求。
(F) 由于访问令牌无效,资源服务器返回无效令牌错误。
(G) 客户端通过使用授权服务器进行身份验证并呈现刷新令牌来请求新的访问令牌。客户端身份验证要求基于客户端类型和授权服务器策略。
(H) 授权服务器验证客户端并验证刷新令牌(如果有效,则发出新的访问令牌(以及可选的新刷新令牌)。
OAuth 2.0 与 OAuth 1.0 的关系
OAuth 1.0 协议 (RFC5849)是社区小型临时努力的结果。OAuth 2.0 协议不向后兼容 OAuth 1.0。这两个版本可能在网络上共存,实现可能会选择支持这两个版本。OAuth 2.0 协议与 OAuth 1.0 协议共享的实施详细信息很少。