OAuth是第三方应用受权(Authorization)的开放标准,目前最新版本是2.0,如下将要介绍的内容和概念主要来源于该版本。 恐篇幅太长,OAuth 的诞生背景就不在这里赘述了,可参考 The OAuth 2.0 Authorization Framework。html
四种角色定义:git
协议端点(URI):OAuth给受权过程定义了Authorization、Token和Redirection三种端点。Authorization端点用来完成用户受权,在受权码模式(Authorization Code)和隐含模式(Implicit)下被用到;Token端点用来交换与获取access token,不能包含fragment(hash),在隐含模式(Implicit)下则无需提供该端点;Redirection端点用来接收受权凭证,Public客户端或者Implicit受权的Confidential客户端必须注册其Redirection端点。promise
客户端类型:OAuth根据是否可以进行安全认证定义了两种客户端类型:机密型客户端(Confidential)和公开型客户端(Public)。其中机密型客户端有Web应用,公开型客户端包括User Agent Based和Native应用。客户端的类型注册时肯定,不能由受权服务器假定。若是一套应用包含多个不一样类型的客户端,这些不一样部分应分开单独注册。浏览器
客户端认证(Client Authentication):客户端认证当知足受权服务器的安全要求,对机密型客户端的认证可依赖受权服务器发布的认证凭证(好比Password, Public/Private密钥对),而要对公共客户端进行认证极可能是不可靠的。客户端在每次请求中只能使用一种认证方法,若是客户端持有Password,可采用HTTP Basic认证或request-body传递身份凭证参数方法。客户端认证带来的益处:安全
访问令牌(Access Token)是什么?Access Token是访问被保护资源的凭证,一个用来代表被授予权限的字符串,能够是一种可取回受权信息的标识,也能够自包含受权信息于内。可参考 RFC6750 - OAuth 2.0 Bearer Token Usage 。服务器
更新令牌(Refresh Token)是什么?当Access Token无效或过时后,客户端将使用Refresh Token来请求受权服务器更新Access Token,除此而外别无他用。一般Refresh Token是受权服务器在发布新Access Token的同时可选发布的,与客户端绑定并长期有效,可是只有受权码模式(Authorization Code)和用户密码模式(Resource Owner Password Credentials)支持Refresh Token。受权服务器须执行以下操做:cookie
Transport Layer Security (TLS):受权服务器和资源服务器都必须实现TLS,至于客户端最好也实现TLS。若是客户端没有实现TLS,受权服务器在发出重定向以前应向用户发出安全告警信息。session
OAuth受权的基本流程以下:app
OAuth针对不一样场景详细定义了四种受权模式:受权码模式(Authorization Code)、隐含模式(Implicit)、用户密码模式(Resource Owner Password Credentials)和客户端证书模式(Client Credentials)。另外,你也可使用其余扩展模式。ide
一. 受权码模式(Authorization Code)
受权码模式是流程最严密的受权模式,可是若是被用于Public客户端受权,因为该客户端不能持有客户端证书,所以没法进行身份认证。
1. 用户访问客户端,后者将前者导向受权服务器 2. 用户选择是否给予客户端受权 3. 假设用户给予受权,受权服务器将用户导向客户端事先指定的"重定向URI"(redirection URI),同时附上一个受权码 4. 客户端收到受权码,附上早先的"重定向URI",向受权服务器申请令牌。这一步是在客户端的后台的服务器上完成的,对用户不可见 5. 受权服务器核对了受权码和重定向URI,确认无误后,向客户端发送访问令牌(access token)或者更新令牌(refresh token)
该流程中客户端先获取受权码再交换访问令牌,彷佛获取受权码显得多余?其实受权码除了表明受权范围以外,还避免了暴露访问令牌于用户端:
The authorization code provides a few important security benefits,such as the ability to authenticate the client, as well as the transmission of the access token directly to the client without passing it through the resource owner's user-agent and potentially exposing it to others, including the resource owner
二. 隐含模式(Implicit)
受权码模式的简化版,跳过了"受权码"这一步,可适用于在浏览器中实现的应用,访问令牌暴露于用户端;在该模式下,受权服务器不会认证客户端,不能使用Refresh Token,一旦Access Token过时,须要从新进行受权处理;隐含模式是一个基于redirection的流,在某些状况下,客户端身份是能够经过redirection URI来验证的。在受权码模式可用的状况下,应权衡隐含模式的便利性和安全性。
1. 客户端将用户导向认证服务器 2. 用户决定是否给于客户端受权 3. 假设用户给予受权,认证服务器将用户导向客户端指定的"重定向URI",并在URI的Hash部分包含了访问令牌 4. 浏览器向Web-Hosted服务器发出请求,其中不包括上一步收到的Hash值 5. Web-Hosted服务器返回一个网页,其中包含的代码能够获取Hash值中的令牌 6. 浏览器执行上一步得到的脚本,提取出令牌 7. 浏览器将令牌发给客户端
三. 用户密码模式(Resource Owner Password Credentials)
用户向客户端提供本身的用户名和密码,客户端使用这些信息向受权服务器索要受权,但不得保存用户的密码。须在用户对客户端高度信任(好比客户端是操做系统的一部分,或者由一个著名公司出品,或者客户端是本公司出品),而认证服务器没法在其余受权模式下完成受权的状况下,才能考虑使用这种模式。
1. 用户向客户端提供用户名和密码 2. 客户端将用户名和密码发给认证服务器,向后者请求令牌 3. 认证服务器确认无误后,向客户端提供访问令牌
四. 客户端证书模式(Client Credentials)
顾名思义,客户端模式不是针对单个用户的受权,而是针对客户端受权,适用于受保护资源已经处于客户端控制之下(至关于资源全部者)或者受权服务器已经预先配置好客户端访问权限的的状况。
1. 客户端向认证服务器进行身份认证,并要求一个访问令牌 2. 认证服务器确认无误后,向客户端提供访问令牌
流程参数解释:此处再也不详述,可参考理解OAuth 2.0 或 RFC6749
五. 受权模式选择
When choosing between the implicit grant type and the authorization code grant type, the following should be considered: . Native applications that use the authorization code grant type SHOULD do so without using client credentials, due to the native application's inability to keep client credentials confidential. . When using the implicit grant type flow, a refresh token is not returned, which requires repeating the authorization process once the access token expires.
User Agent Based应用通常适用隐含模式(Implicit)
六. OAuth不是认证协议
OAuth消费认证(Authentication)而不提供认证,所以OAuth必须结合第三方认证协议如 OpenID Connect:OAuth 2.0协议之上的简单身份层 才可以使用。但OAuth协议中确实有些内容说的就是认证事件,给人的感受就是它已定义了认证流程,固然也就算是有效的认证协议了,这是很容易让人误解的;其实啊,定义认证流根本就不是OAuth的题中之意(好比用户注册这个认证流中的重要环节就不是OAuth所关心的内容,因此也就未曾定义)。下边的引文来自 The OAuth 2.0 Authorization Framework :
Before initiating the protocol, the client registers with the authorization server. The means through which the client registers with the authorization server are beyond the scope of this specification but typically involve end-user interaction with an HTML registration form.
只是认证和受权硬生生地割裂开来,井水不犯河水是不可能的,因此OAuth里边也只是简单地提到了与受权流相关的认证流要害节点以使受权流的定义完整,而没有详细定义认证流,这也是本人刚开始认为OAuth是一个弱认证受权协议的缘由。下边的引用文字来自 User Authentication with OAuth 2.0:
OAuth 2.0 is not an authentication protocol.
an OAuth process does usually include several kinds of authentication in its process:
the resource owner authenticates to the authorization server in the authorization step,
the client authenticates to the authorization server in the token endpoint, and there may be others.
The existence of these authentication events within the OAuth protocol does not translate to the
Oauth protocol itself being able to reliably convey authentication.
假如OAuth能够彻底抛弃所涉及的任何认证流部分,也就不会有人认为OAuth也是认证协议了,而一个完整的认证协议应该是这样的:
Authentication in the context of a user accessing an application tells an application who
the current user isand whether or not they're present. A full authentication protocol will probably
also tell you a number of attributes about this user, such as a unique identifier, an email address,
and what to call them when the application says "Good Morning". Authentication is all about the
user and their presence with the application, and an internet-scale authentication protocol needs
to be able to do this across network and security boundaries.
七. 采用OAuth认证的常见陷阱
八. 安全风险
The authorization server MUST NOT issue client passwords or other client credentials to native application or user-agent-based application clients for the purpose of client authentication. The authorization server MAY issue a client password or other credentials for a specific installation of a native application client on a specific device. ...... A valid redirection URI is not sufficient to verify the client's identity when asking for resource owner authorization but can be used to prevent delivering credentials to a counterfeit client after obtaining resource owner authorization.
更新令牌(Refresh Tokens):受权服务器能够给Web客户端和Native客户端发布Refresh Token。Refresh Token在整个生命周期中都应该保持机密性,不能泄露给任何无关的第三方;Refresh Token必须与客户端身份相绑定;Refresh Token不能未获受权而被生成、修改、猜想产生
the authorization server could employ refresh token rotation in which a new refresh token is issued with every access token refresh response. The previous refresh token is invalidated but retained by the authorization server. If a refresh token is compromised and subsequently used by both the attacker and the legitimate client, one of them will present an invalidated refresh token, which will inform the authorization server of the breach
受权码(Authorization Codes):受权码有效期短,单一用途
If the authorization server observes multiple attempts to exchange an authorization code for an access token, the authorization server SHOULD attempt to revoke all access tokens already granted based on the compromised authorization code.
A CSRF attack against the client's redirection URI allows an attacker to inject its own authorization code or access token, which can result in the client using an access token associated with the attacker's protected resources rather than the victim's (e.g., save the victim's bank account information to a protected resource controlled by the attacker). The client MUST implement CSRF protection for its redirection URI. This is typically accomplished by requiring any request sent to the redirection URI endpoint to include a value that binds the request to the user-agent's authenticated state (e.g., a hash of the session cookie used to authenticate the user-agent). The client SHOULD utilize the "state" request parameter to deliver this value to the authorization server when making an authorization request.
To prevent this form of attack, native applications SHOULD use external browsers instead of embedding browsers within the application when requesting end-user authorization. For most newer browsers, avoidance of iframes can be enforced by the authorization server using the (non-standard) "x-frame-options" header. This header can have two values, "deny" and "sameorigin", which will block any framing, or framing by sites with a different origin, respectively. For older browsers, JavaScript frame-busting techniques can be used but may not be effective in all browsers
九. 相关参考