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
九. 相關參考