1、介紹
https://tools.ietf.org/html/rfc6749
傳統的client-server授權模型,客戶端通過使用憑證(通常的使用者名稱和明文密碼)訪問服務端受保護的資源,為了能夠讓第三方應用程式訪問受保護的資源,需要將憑證共享給第三方。
這就產生了一些問題和限制:
- 為了以後能夠持續訪問,第三方應用程式可能會儲存憑證(使用者名稱、密碼)。
- 儘管密碼本身存在安全弱點,但伺服器必須支援密碼驗證。
- 由於無法限制受保護資源的訪問粒度和期限,第三方應用程式獲得了對受保護資源的廣泛訪問。
- 除了修改密碼外,無法對單個第三方或者所有第三方吊銷憑證。
OAuth通過引入一個授權層,並分離客戶端和資源擁有者成不同的角色來解決這個問題。在OAuth中,通過發行不同的訪問令牌(包括資源訪問範圍、生命週期、其他訪問屬性),而不是資源本身,來限制第三方應用程式訪問受保護資源(資源擁有者保護並宿主在資源伺服器)的粒度和期限,而不是直接把憑證(使用者名稱和密碼)提供給客戶端。
例如:一個終端使用者(資源擁有者)可以授權一個列印服務(客戶端)來訪問宿主在圖片共享伺服器(資源伺服器)上的受保護的圖片(資源),而不用共享憑證(使用者名稱和密碼)給列印服務(客戶端)。
1.1 角色
在OAuth中定義了4中角色:
資源所有者(resource owner)
能夠對受保護資源授予訪問權的實體,當資源的所有者是人時,指的就是我們的終端使用者。
資源服務(resource server)
宿主受保護的資源。能夠接受和響應使用訪問令牌(access tokens)對受保護資源的請求。
客戶端(client)
對受保護資源發起請求的應用程式。可能是一個服務、桌面應用程式、或者其他裝置。
授權服務(authorization server)
成功認證資源所有者和獲得授權後,發行訪問令牌給客戶端。
授權服務和資源服務之間的互動不在超過該規範,授權服務和資源服務可能是同一個服務,也可能是不同的服務。單個授權伺服器應該可以發行由多個資源伺服器接受的訪問令牌。
1.2 協議流程
+--------+ +---------------+
| |--(A)- Authorization Request ->| Resource |
| | | Owner |
| |<-(B)-- Authorization Grant ---| |
| | +---------------+
| |
| | +---------------+
| |--(C)-- Authorization Grant -->| Authorization |
| Client | | Server |
| |<-(D)----- Access Token -------| |
| | +---------------+
| |
| | +---------------+
| |--(E)----- Access Token ------>| Resource |
| | | Server |
| |<-(F)--- Protected Resource ---| |
+--------+ +---------------+
(A) 客戶端向資源所有者請求授權,這時授權請求可能直接提交給資源所有者,也可能提交給授權服務(扮演一個授權終端)。
(B) 客戶端獲得一個資源所有者授權許可的憑證。授權許可型別可以使用規範中定義的4中型別,也可以自定型別(注意:授權服務需要支援自定義授權許可型別)。
(C) 客戶端通過提交授權許可憑證給授權服務,請求訪問令牌。
(d) 授權服務認證客戶端並驗證授權許可憑證,頒發訪問令牌。
(E) 客戶端通過提交已認證的訪問令牌,請求受保護的資源。
(F) 資源服務驗證訪問令牌,如果有效,響應請求。
注意:客戶端獲取獲取授權許可憑證的首選方法,就是使用授權服務作為一箇中介。
1.3 授權許可
代表資源所有者授權的一個憑據,可以用獲取訪問令牌;OAuth2.0 協議定義了4中授權許可型別:授權碼模式、隱性模式、資源所有者密碼憑證、客戶端憑證。也可以自定義擴充套件的授權許可型別。
1.3.1 授權碼模式(Authorization Code)
授權碼通過一個授權伺服器獲得,授權服務在客戶端和資源所有者之間扮演一箇中介。客戶端不是直接從資源所有者請求授權,而是將資源所有者指向授權伺服器,然後授權伺服器在將資源所有者引導到客戶端,並攜帶授權碼。在重定向資源伺服器到客戶端之前,授權伺服器認證資源所有者並獲得授權。注意授權伺服器僅僅認證資源所有者,並不會共享憑證給客戶端。
授權碼提供了一些重要的安全好處,例如認證客戶端,也可以用於直接獲取令牌,而不再需要經過資源所有者,也可以暴露給其他人,包括資源所有者。
1.3.2 隱性模式(Implicit)
隱性模式是授權碼模式的簡化版,使用一個指令碼語言(例如:JavaScript)優化了客戶端的實現。在隱性模式中,資源所有者授權後,並不會為客戶端頒發授權碼,而是直接頒發一個訪問令牌。因為並沒有頒發中間憑證(例如:授權碼),授權許可型別是隱性的,故稱之為隱性模式。
在隱式授權流中釋出訪問令牌時,授權伺服器不驗證客戶端。在某些情況下,客戶端標識可以通過傳遞訪問令牌給客戶端的重定向URI來識別,訪問令牌能夠暴露給資源所有者和其他資源所有者訪問的應用程式。隱性模式提高了某些客戶端的響應速度和效率(例如:作為瀏覽器應用程式實現的客戶端),因為它減少了獲取訪問令牌所需的往返次數。但是當安全性要求很高的場景下,這種模式需要權衡,特別是當授權碼模式可用的情況下。
1.3.3 客戶端的驗證授權模式(Resource Owner Password Credentials)
客戶端的驗證授權(即使用者名稱和密碼)可以直接作為授權許可,來獲得訪問令牌。只有當資源所有者充分信任(例如:客戶端是整個系統的一部分,或者是特權應用程式,或者其他授權許可不可用時)客戶端的情況下,才使用該模式。儘管這種授權許可型別要求客戶端直接訪問資源所有者的憑據,但資源所有者憑證只能用於單個請求,來交換訪問令牌。通過使用長壽命的訪問令牌或者重新整理令牌,該模式消除了客戶端儲存資源所有者憑證(以備將來使用)的需求。
1.3.4 客戶端憑證模式(Client Credentials)
當授權範圍僅限於受客戶端控制的受保護資源時,客戶端憑據可以用作授權許可。通常當客戶以自己的名義行事時(此時,客戶端也是一個資源所有者),客戶端許可會被使用。
1.4 訪問令牌(Access Token)
訪問令牌是用於訪問受保護資源的憑證。訪問令牌是表示向客戶機頒發的授權的字串,該字串通常對客戶端不透明。該令牌帶有特定的範圍(控制資源訪問粒度)和持續時間,由資源所有者授權許可,資源伺服器和授權伺服器強行執行。令牌可能表示用於檢索授權資訊的識別符號,也可能以可驗證方式自包含授權資訊(一個訪問令牌字串由一些資料和一個簽名信息組成)。
訪問令牌是一個抽象的層,裡面放置著各種各樣資源伺服器能夠理解的構造資訊(例如:資源的訪問範圍、持續時間等等)。通過抽象,也使訪問令牌的頒發不獲得授權許可更受限制,同時也消除了資源伺服器需要理解多種認證方法的需要。
基於資源伺服器安全(例如:加密屬性)的需求,訪問令牌可能有不同的格式、結構、使用方法。
1.5 重新整理令牌(Refresh Token)
重新整理令牌是一個用於獲取訪問令牌的憑證。重新整理令牌由授權伺服器頒發給客戶端,如果當前的訪問令牌無效或者過期時,獲取一個新的訪問令牌;或者強制再請求一個訪問令牌(可能相同或更窄範圍的訪問令牌)。與資源所有者相比,訪問令牌有更短的生命週期和更少的許可權。對於授權伺服器而言,頒發一個重新整理令牌是可選的,但是當要頒發重新整理令牌時,一般情況下,重新整理令牌是伴隨著訪問令牌一起頒發的。
重新整理令牌代表資源所有者對客戶端給予授權許可的字串,通過對客戶端不透明。令牌表示用於檢索授權資訊的識別符號。與訪問令牌不同,重新整理令牌僅用於授權伺服器,且從不傳送到資源伺服器。
+--------+ +---------------+
| |--(A)------- Authorization Grant --------->| |
| | | |
| |<-(B)----------- Access Token -------------| |
| | & Refresh Token | |
| | | |
| | +----------+ | |
| |--(C)---- Access Token ---->| | | |
| | | | | |
| |<-(D)- Protected Resource --| Resource | | Authorization |
| Client | | Server | | Server |
| |--(E)---- Access Token ---->| | | |
| | | | | |
| |<-(F)- Invalid Token Error -| | | |
| | +----------+ | |
| | | |
| |--(G)----------- Refresh Token ----------->| |
| | | |
| |<-(H)----------- Access Token -------------| |
+--------+ & Optional Refresh Token +---------------+ 圖 2: 重新整理一個過期的訪問令牌
(A) 客戶端請求授權伺服器的認證,並提交授權許可。
(B) 授權伺服器認證客戶端並驗證授權許可後,頒發訪問令牌和重新整理令牌。
(C) 客戶端向資源伺服器發出受保護的資源請求,並提交訪問令牌。
(D) 資源伺服器驗證訪問令牌後,把受保護的資源響應給客戶端。
(E) 步驟(C)和(D)重複,直到訪問令牌過期。如果客戶端知道訪問令牌過期,就會跳到步驟(G)。否則,它將建立另一個受保護的資源請求。
(F) 由於訪問令牌無效,資源伺服器返回一個無效的令牌錯誤。
(G) 客戶端請求一個新的訪問令牌,並提交重新整理令牌。客戶端身份驗證需求基於客戶機型別和授權伺服器策略。
(H) 授權伺服器認證客戶端並驗證重新整理令牌後,如果有效,頒發一個新的訪問令牌(此時,是否頒發一個新的重新整理令牌是可選的)。
1.6 TLS版本(TLS Version)
基於廣泛部署和已知的安全漏洞,TLS版本都是隨著時間變化而變化的。TLS版本1是最廣泛部署的版本,將提供最廣泛的互操作性。具體實現還可以支援滿足其安全要求的附加傳輸層安全機制。
1.7 HTTP重定向(HTTP Redirections)
該規範充分利用了Http重定向,客戶端和授權伺服器將資源所有者使用者代理重定向到另外的目的地。雖然規範中的示例顯示了HTTP 302狀態程式碼的使用,但是允許使用者代理運用任何其他方法來完成此重定向,並被認為是實現細節。
1.8 互操作性(Interoperability)
OAuth 2提供了一個明確的安全特性豐富的授權框架。然而,作為一個豐富且高度可擴充套件的框架,有許多可選元件,這一規範本身可能會產生廣泛的非互操作性實現。此外,該規範還提供部分必需的部分或完全未定義的元件(例如,客戶端註冊、授權伺服器功能、端點發現)。沒有這些元件,針對一個特定的授權伺服器,資源伺服器的互操作,客戶端必須手動配置。這個框架的設計帶有明確的期望,未來的工作將定義實現完整Web規模互操作性所必需的規範配置檔案和擴充套件。
1.9 符號約定(Notational Conventions)
該協議中的關鍵詞 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT","SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL"在 [RFC2119] 中被詳細的描述。該規範使用[RFC5234]中的 the Augmented Backus-Naur Form (ABNF)符號規範。此外,規則的URI引用被包含在“統一資源識別符號(URI):通用語法”[ rfc3986 ]中。某些安全相關的術語被定義在[RFC4949]中,這些術語包括但不限於 "attack", "authentication", "authorization", "certificate","confidentiality", "credential", "encryption", "identity", "sign","signature", "trust", "validate", and "verify"。除非另有說明,所有協議引數名稱和值都是區分大小寫的。
2、客戶端註冊(Client Registration)
在啟動協議之前,客戶端使用授權伺服器進行註冊。客戶端通過授權伺服器註冊的方式超過了該協議的範圍,但是一般都是終端使用者通過一個HTML表單提交註冊。客戶端註冊並不需要客戶端和授權伺服器的直接互動,只要授權伺服器支援,可以使用各種各樣的放肆進行註冊並獲取已註冊客戶端的屬性。例如:可以使用一個自發布或者第三方釋出的宣告(assertion)或者授權伺服器通過一個信任的通道來進行客戶端的發現。
當註冊一個客戶端時,客戶端開發人員應該:
- 指定客戶端型別
- 提供客戶端重定向的URI
- 包括授權伺服器所要求的任何其他資訊(例如,應用程式名稱,網站,描述,Logo影象,服務條款等等)。
2.1 客戶端型別(Client Types)
基於客戶端和授權伺服器,安全認證的能力(例如:客戶憑證的保密性),OAuth定義了兩種型別的客戶端。
保密型別(confidential)
能夠維護其憑證的保密性的客戶端(例如:客戶端在一個安全的伺服器上,客戶端的訪問受到限制),能夠通過其他方式來保證客戶端認證的安全性。
公開型別(pulic)
不能夠維護其憑證的保密性的客戶端(例如:在資源所有者的裝置上執行客戶端,如已安裝的本機應用程式或基於Web瀏覽器的應用程式),不能夠通過其他方式來保證客戶端認證的安全性。
客戶機型別指定是基於授權伺服器對安全認證的定義及其可接受的客戶端證書的暴露級別。授權伺服器不應該對客戶端型別做出假設。客戶機可以實現為一組分散式元件,每個元件具有不同的客戶機型別和安全上下文(例如,一個分散式客戶端既有基於伺服器的機密元件,又有基於公共瀏覽器的元件);如果傳統授權伺服器不能夠對這樣的客戶端提供支援或者註冊引導,客戶應將每個元件註冊為單獨的客戶機。
本規範是圍繞以下客戶端配置檔案設計的:
web 應用程式(web application)
Web應用程式是在Web伺服器上執行的機密客戶端。資源所有者通過在其使用的裝置上的通過使用者代理(瀏覽器)中呈現的HTML使用者介面訪問客戶端。客戶端憑據以及向客戶機發出的任何訪問令牌都儲存在Web伺服器上,不會被資源所有者暴露或訪問。
基於使用者代理的應用程式(user-agent-based application)
基於使用者代理的應用程式是一個公共客戶端,其中客戶端程式碼從Web伺服器下載並在由資源所有者所使用的裝置的使用者代理內執行。 所以,對於資源所有者,協議資料和憑證可以很容易獲得。由於這些應用程式駐留在使用者代理中,所以在請求授權時可以無縫地使用使用者代理功能。
本地應用程式(native application)
本機應用程式是安裝在資源所有者使用的裝置上並執行的公共客戶機。對於資源所有者,協議資料和證書是可得到的。假設可以提取應用程式中包含的任何客戶端身份驗證憑據。另一方面,動態釋出的憑據(如訪問令牌或重新整理令牌)可以收到可接受的保護級別。至少,這些憑據被保護免受應用程式可能互動的惡意伺服器的保護。某些情況下,這些應用程式也會受到保護免受駐留在同一裝置的其他應用程式的干擾。
2.2 客戶端標識(Client Identifier)
授權伺服器向註冊客戶端頒發客戶端識別符號------表示客戶端提供的註冊資訊的唯一字串。客戶機識別符號不是祕密,它暴露給資源所有者,不能單獨用於客戶端身份驗證。
客戶端識別符號對授權伺服器是唯一的。
客戶識別符號字串大小該規範未定義。客戶機應該避免對識別符號大小做出假設。授權伺服器應該記錄它所頒發的任何識別符號的大小。
2.3 客戶端認證(Client Authentication)
如果客戶機型別是機密的,客戶機和授權伺服器建立適合於授權伺服器的安全需求的客戶端身份驗證方法。授權伺服器可以接受滿足其安全要求的任何形式的客戶端身份驗證。機密客戶機通常釋出(或建立)一組客戶端證書,用於與授權伺服器進行身份驗證(例如,密碼、公鑰/私鑰對)。授權伺服器可以和公共客戶端建立客戶端認證方法。但是,授權伺服器不能依賴公共客戶端身份驗證,以識別客戶機。在每個請求中,客戶端不能使用多個身份驗證方法。
2.3.1 客戶端密碼(Client Password)
擁有客戶端密碼的客戶機可以使用HTTP基本身份驗證方案和授權伺服器進行身份驗證。客戶端標識使用"application/x-www-form-urlencoded"編碼演算法進行編碼,編碼值用作使用者名稱。客戶端密碼使用相同的演算法進行編碼,並用作密碼。授權伺服器必須支援HTTP基本身份驗證方案,以驗證客戶端密碼並頒發密碼。
例如:授權 Basic czZCaGRSa3F0Mzo3RmpmcDBaQnIxS3REUmJuZlZkbUl3,還有一種可選的方案就是,在請求頭中包含兩個引數(client_id和client_secret),這種方案一般不推薦,除非客戶端不能夠使用 HTTP Basic authentication scheme (或者其他的基於密碼的HTTP authentication scheme)。引數只能在請求體中傳輸,不能包含在請求URI中。
2.3.1 其他認證方法(Other Authentication Methods)
授權伺服器可以支援符合其安全要求的任何合適的HTTP認證方案。在使用其他身份驗證方法時,授權伺服器必須定義客戶端識別符號(註冊記錄)和身份驗證方案之間的對映。
2.4 未註冊的客戶端(Unregistered Clients)
該規範沒有包含未註冊的客戶端的使用。這種客戶機的使用超出了本規範的範圍,需要對其互操作性影響進行額外的安全性分析和審查。
3、協議的端點(Protocol Endpoints)
授權處理利用兩個授權伺服器終結點:
- 授權端點
客戶端通過使用者代理重定向到該端點獲得資源所有者的授權。
- 令牌端點
客戶機用來交換訪問令牌的授權許可,通常具有客戶端身份驗證。
- 重定向端點
授權伺服器用於通過資源所有者使用者代理將包含授權憑證的響應返回給客戶端。
並不是每一個授權許可型別都會使用這些終結點;當然擴充套件的授權許可型別可以定義自己的終結點。
3.1 授權端點(Authorization Endpoint)
授權終結點與資源所有者互動獲取一個授權許可。首先授權伺服器必須稽核資源所有者的身份資訊(授權伺服器採用什麼方式認證資源所有者的身份(例如:使用者名稱、密碼、會話Cookie),超出了本規範的訪問)。
授權URI可能包含 "application/x-www-form-urlencoded" 格式的必須的查詢元件(query parameters)。端點URI不能包含碎片元件(fragment component)。
由於對授權端點的請求,導致使用者身份驗證和明文證書的傳輸。當傳送請求到授權端點時,授權伺服器必須要求使用TLS。授權伺服器必須支援“Get”方法,也可以支援“Post”方法。
傳送請求時,沒有值的引數會被省略。授權伺服器必須忽略無法識別的請求引數。請求和響應引數不應包含超過一次。
3.1.1 響應型別(Response Type)
授權終結點被授權碼模式和隱式模式使用。
客戶端通過下列引數來通知授權伺服器期望建立的授權許可型別流:
response_type:必須。授權碼模式時,該值必須為“code”。隱性模式時,該值必須為“token”。還可以為我們自己註冊的擴充套件值。如果一個授權請求確實該引數,或者授權伺服器無法理解該引數,將返回一個錯誤的響應。
3.1.2 重定向終結點(Redirection Endpoint)
在完成與資源所有者的互動之後,授權伺服器將資源所有者的使用者代理引導回客戶端。重定向終結點URI必須為完整的URI,端點的URI可能包括一個“application/x-www-form-urlencoded”格式的查詢元件,但不能包含“fragment ”元件。
3.1.2.1 終結點請求機密性(Endpoint Request Confidentiality)
當請求的響應型別為“code”或“token”時,或者當我們要傳送機密的憑證資訊時,這個時候需要使用TLS。該規範並不強制使用TLS,因為在編寫此規範時,要求客戶機部署TLS是許多客戶機開發人員的一個重要障礙。如果TLS不可用,在重定向到授權伺服器之前,應該警告資源所有者不安全端點的情況。
傳輸層安全性的缺乏會嚴重影響客戶端和授權訪問的受保護資源的安全性。當授權過程作為客戶端委託的終端使用者身份驗證的一種形式時(例如:第三方登入服務),傳輸層安全性的使用尤為重要。
3.1.2.1 註冊要求(Registration Requirements)
授權伺服器只接受下面的客戶端的註冊:
- 公共客戶端
- 使用隱式授權型別的機密客戶端
在使用授權伺服器之前,應該要求所有的客戶端來註冊他們的完成授權後的重定向端點。客戶機可以使用“state”請求引數來實現每個請求定製。如果要求完全重定向URI的註冊是不可能的,授權伺服器應該要求URI scheme, authority, and path的註冊(允許客戶端動態的改變重定向URI的查詢組)。授權伺服器也允許客戶端註冊多個重定向端點。缺少重定向URI註冊要求,增加攻擊者利用授權端點的風險。
3.1.2.1 動態配置(Dynamic Configuration)
如果多個重定向URI已註冊,或者只有重定向URI的一部分已被註冊,或者重定向URL沒有被註冊,則在客戶端的授權請求的查詢元件中,必須包含"redirect_uri"引數。當一個重定向的URI被包含在授權請求中時,授權伺服器必須跟以註冊的客戶端重定向URI作比較和匹配,如果沒有就跟客戶端本身的URL作比較。
3.1.2.2 無效端點(Invalid Endpoint)
如果由於授權請求引數缺失,無效,或者不能匹配無效的URI,授權伺服器應該告知一個錯誤給資源所有者。
3.1.2.2 端點內容(Endpoint Content)
返回給客戶端的請求通常是一個HTML文件。如果HTML響應作為重定向請求的結果直接送達,則HTML文件中包含的任何指令碼都將執行對重定向URI及其所包含的憑據的完全訪問。在重定向端點的響應中,客戶端不應該包含任何第三方的指令碼,相反它應該提取出憑證,然後重定向使用者代理到另外的不會暴露憑證資訊的端點。如果,包含第三方指令碼,客戶端必須保證首先執行自己的指令碼。
3.2 令牌端點(Token Endpoint)
令牌端點被客戶端用來獲取訪問令牌(通過呈現一個包含授權資訊的授權許可)或者重新整理令牌。除了隱式授權型別(訪問令牌是直接頒發的。)外,其他的三種授權許可型別都會使用令牌端點。
客戶端獲取令牌端點地址的方法超過了本規範的範疇,但是通常都是在一個服務文件中提供。
因為對令牌端點的請求會涉及到憑證的明文傳輸,所有要求必須使用TLS,並且必須使用Post方法。
3.2.1 客戶端授權(Client Authentication)
當向令牌端點發起請求時,為機密客戶端和其他的客戶端頒發的客戶端憑證必須和授權伺服器進行授權。
- 強制頒發重新整理令牌和授權碼給客戶端。當授權碼被以一種非安全的方式傳輸到重定向端點,或者重定向URI沒有被完全的註冊。
- 通過禁用客戶端或更改其憑據來,從受損客戶機中恢復,從而防止攻擊者濫用被盜的重新整理令牌。畢竟改變單一的一組客戶端憑證比登出整個重新整理令牌要快的多。
- 實現認證管理最佳實踐,需要定期證書輪換。實現整套重新整理令牌的輪換是具有挑戰性的,而實現單一的客戶端證書輪換非常的簡單。
當傳送請求的令牌端點時,客戶可以使用“client_id”請求引數標識本身。在通過“authorization_code”和“grant_type”對令牌端點發起請求時,未經身份驗證的客戶端必須傳送“client_id”以防止自己無意間接受一個來自於其他客戶端“client_id”的程式碼。這樣也防止客戶端的授權碼被替換,但是這並不對受保護的資源提供額外的安全性保障。
3.2 訪問令牌範圍(Access Token Scope)
通過在請求中新增引數"scope",授權端點和令牌端點允許客戶端指定請求所訪問的範圍。同樣的,授權伺服器也是用“scope”響應引數來表示頒發給客戶端的訪問令牌的範圍。“scope”引數的值表示為空格分隔的、區分大小寫的字串的列表。該字串由授權伺服器定義。
基於授權伺服器的策略和資源所有者的指示,授權伺服器可能會完全或者部分忽略客戶端請求的“scope”引數。如果已釋出的訪問令牌範圍與客戶端請求的範圍不同,授權伺服器必須包含“scope”響應引數,告知客戶端實際範圍授予。
如果客戶端在請求授權時省略了範圍引數,則授權伺服器必須使用預先定義的範圍預設值處理請求,或者失敗指示無效範圍的請求。授權伺服器應該記錄它的範圍要求和預設值。
4、獲取授權(Obtaining Authorization)
為了獲得一個訪問令牌,客戶端需要向資源所有者獲得授權,授權以許可(authorization grant)的形式被呈現。OAuth定義了4中許可型別:authorization code(授權碼), implicit(隱性),resource owner password credentials(資源所有者密碼憑證), and client credentials(客戶端憑證)。它也提供了擴充套件的機制來定義額外的授權許可型別。
4.1 授權碼許可型別(Authorization Code Grant)
授權碼許可型別可以用於獲取訪問令牌和重新整理令牌,它是為機密客戶端憑證優化的。由於這是一個基於重定向的流程,客戶端必須能夠與資源所有者的使用者代理(通常是一個webbrowser)進行互動,並能夠接收來自於授權伺服器的傳入請求(重定向)。
+----------+
| Resource |
| Owner |
| |
+----------+
^
|
(B)
+----|-----+ Client Identifier +---------------+
| -+----(A)-- & Redirection URI ---->| |
| User- | | Authorization |
| Agent -+----(B)-- User authenticates --->| Server |
| | | |
| -+----(C)-- Authorization Code ---<| |
+-|----|---+ +---------------+
| | ^ v
(A) (C) | |
| | | |
^ v | |
+---------+ | |
| |>---(D)-- Authorization Code ---------' |
| Client | & Redirection URI |
| | |
| |<---(E)----- Access Token -------------------'
+---------+ (w/ Optional Refresh Token)
注意:通過上圖可以看到,到客戶端經過使用者代理時,(A)、(B)、(C)被分成了兩步。
圖3:授權碼流程
(A)客戶端通過重定向資源所有者的使用者代理重定向到授權伺服器(注意資源服務與授權服務不是同一臺伺服器),並在請求中包含客戶端識別符號、請求的範圍、本地狀態、重定向URI等引數,一旦授權伺服器許可或者拒絕後,就會返回到使用者代理。
(B)授權伺服器認證資源所有者(通過使用者代理),確定資源所有者的許可,或者拒絕客戶端的訪問請求。
(C)假如資源所有者許可訪問,根據早前在客戶端認證階段提供的重定向URI,並攜帶引數授權碼和本地狀態(早前在客戶端認證階段提供的),重定向使用者代理到客戶端。
(D)通過在請求中包含授權碼和重定向URI,客戶端從令牌端點獲取訪問令牌。
(E)授權伺服器驗證授權碼和重定向URI(和客戶端認證階段提供的重定向URI進行匹配),如果有效,攜帶訪問令牌和重新整理令牌(可選)響應返回。
4.1.1 授權請求(Authorization Request)
通過新增下列引數到查詢元件(query component)中(注意使用 "application/x-www-form-urlencoded" ),發起對授權端點URI的請求。
response_type(請求型別):必須,值必須為“code”
client_id(客戶端身份標識):必須
redirect_uri(重定向URI):可選
scope(請求的範圍):可選
state(客戶端本地狀態):必須,客戶機用來維護請求和回撥之間的狀態的不透明值。當將使用者代理重定向回客戶端時,授權伺服器包含此值。該引數應用於防止跨站點請求偽造。
通過Http重定向響應或者其他使用者代理能夠接受的方式,客戶端將資源所有者導向已構建好的URI。例如,客戶端指導使用者代理來發起下面的Http請求:
GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
Host: server.example.com
授權伺服器驗證請求來保證所有必須的引數都存在和有效。如果請求有效,授權伺服器通過認證資源所有者來獲得授權決定。如果授權決定被許可,授權伺服器就會重定向使用者代理到客戶端提供的重定向URI。
4.1.2 授權響應(Authorization Response)
如果資源所有者許可訪問請求,授權服務頒發一個授權碼,並以"application/x-www-form-urlencoded"格式新增下列引數到重定向URI查詢元件(query)中。
code:必須。由授權伺服器生成的授權碼。授權碼被頒發後,必須短暫過期,降低洩露風險,最長的生命週期推薦10分鐘,客戶端只能使用一次授權碼;如果被第二次使用時,授權伺服器必須登出頒發給該授權碼的所有令牌。
state:狀態。如果該引數在之前的客戶端授權請求中被包含,則返回時必須原封不動的帶上此引數。
例如:授權伺服器通過傳送下面的Http 響應重定向使用者代理到客戶端。
HTTP/1.1 302 Found
Location: https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA&state=xyz
客戶端必須忽略不能識別的響應引數,授權碼字串的長度本規範並未定義。客戶端應該避免對授權碼長度的猜測,授權伺服器應該記錄下所頒發的授權碼的長度。
4.1.2.1 錯誤響應(Error Response)
如果由於缺失、無效、不匹配重定向URI和客戶端識別符號,授權伺服器應該通知資源所有者錯誤,不能自動的重定向使用者代理到無效的重定向URI。
如果資源所有者拒絕客戶端的訪問請求,授權碼伺服器應該使用"application/x-www-form-urlencoded"格式新增下列引數到重定向URI的查詢元件(query component)中。
error:必須。一個簡單的、來自於包含下面引數的 ASCII 錯誤程式碼。
invalid_request(無效請求):請求缺少所需的引數,包括無效的引數值,其中包含一次以上的引數,或者是其他格式錯誤的。
unauthorized_client(未授權的客戶端):客戶端沒有授權使用此方法請求授權碼。
access_denied(訪問拒絕):資源所有者或者授權伺服器拒絕請求。
unsupported_response_type(不支援的響應型別):授權伺服器不支援使用此方法獲得授權程式碼。
invalid_scope(無效的請求範圍):請求的範圍無效、未知或格式錯誤。
server_error(伺服器錯誤):授權伺服器遇到意外情況,阻止它執行請求(因為當重定向時,一個500內部錯誤Http狀態碼不能返回給客戶端,所以這個錯誤碼是必須的。)。
temporarily_unavailable(暫時不可用):由於臨時伺服器超載或維護,授權伺服器目前無法處理請求。
error_description(錯誤的描述):可選。提供額外資訊,人類可讀的ASCII碼文字字串。幫助客戶端的開發者理解發生的錯誤。
error_uri(錯誤URI):可選。帶有錯誤資訊的且可讀的Web頁面,用於向客戶端開發人員提供關於錯誤的附加資訊。
state(狀態):可選。如果在客戶機授權請求中存在“state”引數,則需要原封不動的返回。
例如:授權伺服器通過傳送下面的Http 響應重定向使用者代理到客戶端。
HTTP/1.1 302 Found
Location: https://client.example.com/cb?error=access_denied&state=xyz
4.1.3 訪問令牌請求(Access Token Request)
客戶端對令牌端點發送請求,並新增下列引數到查詢元件(query component)中(注意使用 "application/x-www-form-urlencoded" ),在在HTTP請求實體中使用utf-8字元編碼。
grant_type(授權許可型別):必須。值必須為“authorization_code”
code(授權碼):必須。從認證伺服器請求的授權碼。
redirect_uri(重定向URI):必須。如果重定向URI被包含在授權請求中,則值必須與客戶端認證階段包含的重定向URI相同。
client_id(客戶端身份標識):必須。如果客戶端不使用授權伺服器進行身份驗證。如果客戶端型別是機密的,或者客戶端已經被頒發的憑證,或者被分配其他的授權要求,則客戶端必須使用授權伺服器進行身份驗證。
例如,客戶端使用TLS傳送以下HTTP請求:
POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
授權伺服器必須:
- 如果客戶端型別是機密的,或者客戶端已經被頒發的憑證,或者被分配其他的授權要求,則客戶端必須使進行身份驗證。
- 如果客戶端認證被包含,則認證客戶端。
- 確保授權碼被髮送到經身份驗證的機密客戶機,或者被頒發給請求中“client_id”標識的公開客戶端。
- 稽核授權碼是否有效。
- 如果“redirect_uri”被包含在請求中,確保與之前客戶端認證階段提供的“redirect_uri”引數相等。
- 如果客戶端型別是機密的,或者客戶端已經被頒發的憑證,或者被分配其他的授權要求,則客戶端必須使進行身份驗證。
4.1.4 訪問令牌響應(Access Token Response)
如果訪問令牌請求有效並已被授權,則授權服務需頒發一個必須的訪問令牌和一個可選的重新整理令牌。如果請求客戶端認證失敗或者無效,授權伺服器將返回錯誤的響應。
成功響應的例子:
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache {
"access_token":"2YotnFZFEjr1zCsicMWpAA",
"token_type":"example",
"expires_in":3600,
"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
"example_parameter":"example_value"
}
4.2 隱性許可型別(Implicit Grant)
隱式許可型別用於獲取訪問令牌(不支援發行重新整理令牌),並且它對執行特定重定向URI的公共客戶機進行了優化。 這些客戶機通常使用JavaScript等指令碼語言實現,並執行在客戶端中。由於這是一個基於重定向的流程,客戶端必須能夠與資源所有者的使用者代理(通常一個web瀏覽器)進行互動,並且能夠接受來自於授權服務傳入(通過重定向)的請求。
不像授權碼許可型別,客戶端分別請求授權和訪問令牌,而是直接接收訪問令牌作為授權請求的結果。 隱式授權型別不包括客戶端身份驗證,依賴於資源所有者的存在和重定向URI的註冊。因為訪問令牌被編碼到重定向URI中,所以它可能暴露在資源所有者和駐留在同一裝置上的其他應用程式中。
+----------+
| Resource |
| Owner |
| |
+----------+
^
|
(B)
+----|-----+ Client Identifier +---------------+
| -+----(A)-- & Redirection URI --->| |
| User- | | Authorization |
| Agent -|----(B)-- User authenticates -->| Server |
| | | |
| |<---(C)--- Redirection URI ----<| |
| | with Access Token +---------------+
| | in Fragment
| | +---------------+
| |----(D)--- Redirection URI ---->| Web-Hosted |
| | without Fragment | Client |
| | | Resource |
| (F) |<---(E)------- Script ---------<| |
| | +---------------+
+-|--------+
| |
(A) (G) Access Token
| |
^ v
+---------+
| |
| Client |
| |
+---------+
圖4:隱性許可流程 (A)客戶端將資源伺服器的使用者代理導向授權端點,幷包含客戶端標識、請求範圍、本地狀態、重定向URI等引數,一旦訪問被許可,授權伺服器將返回到使用者代理。
(B)授權伺服器認證資源所有者,並確定資源所有者是許可還是拒絕客戶端的訪問請求。
(C)假如資源所有者許可訪問,根據早前在客戶端認證階段提供的重定向URI,並在URI片段(fragment)中包含訪問令牌,重定向使用者代理到客戶端。
(D)使用者代理保留本地UIR片段,向客戶端Web託管資源伺服器發起請求。
(E)客戶端Web託管資源伺服器返回一個web頁面,幷包含能夠在URI片段中的提取訪問令牌(和其他引數)的指令碼。
(F)使用者代理執行指令碼,提取訪問令牌(和其他引數)
(G)使用者代理將訪問令牌傳送給客戶端。
4.2.1 授權請求(Authorization Request)
通過新增下列引數到查詢元件(query component)中(注意使用 "application/x-www-form-urlencoded" ),發起對授權端點URI的請求。
response_type(響應型別):必須。值必須為“Token”。
client_id(客戶端標識):必須。
redirect_uri(重定向URI):可選。
scope(請求的範圍):可選。
state(客戶端本地狀態):推薦。客戶機用來維護請求和回撥之間的狀態的不透明值。當將使用者代理重定向回客戶端時,授權伺服器包含此值。該引數應用於防止跨站點請求偽造。
通過Http重定向,客戶端將資源所有者導向使用上面引數構造的授權伺服器URI請求。例如,客戶端指導使用者代理使用TLS來發起下面的Http請求:
GET /authorize?response_type=token&client_id=s6BhdRkqt3&state=xyz
&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
Host: server.example.com
授權伺服器驗證請求來保證所有必須的引數都存在和有效。授權伺服器必須(因為需要它來攜帶訪問令牌)驗證重定向URI,並與之前客戶端認證提供的重定向URI進行匹配。如果請求有效,授權伺服器通過認證資源所有者來獲得授權決定(或者通過其他標準來獲得授權許可)。如果授權決定被許可,授權伺服器就會重定向使用者代理到客戶端提供的重定向URI。
4.2.2 授權響應(Authorization Response)
如果資源所有者許可訪問請求,授權伺服器就會頒發一個訪問令牌,並以"application/x-www-form-urlencoded"格式新增下列引數到重定向URI片段元件(query fragment)中。
access_token(訪問令牌):必須。
token_type(令牌型別):必須。
expires_in(過期時間):推薦。訪問令牌的生命週期,值“3600”表示訪問令牌將在一個小時後過期。如果省略,授權伺服器,應該設定一個預設值,或者通過其他的方式提供過期時間。
scope(範圍):可選。如果等同於客戶端請求的範圍則可選,否則必須。
state(狀態):可選。如果在客戶機授權請求中存在“state”引數,則必須原封不動的返回。
授權伺服器不能頒發重新整理令牌
例如:授權伺服器通過傳送下面的Http 響應重定向使用者代理。
HTTP/1.1 302 Found
Location: http://example.com/cb#access_token=2YotnFZFEjr1zCsicMWpAA
&state=xyz&token_type=example&expires_in=3600
開發人員應該注意到一些使用者代理不支援在HTTP“location”響應頭欄位中包含一個片段元件。這樣的客戶端會要求使用其他方法重定向客戶端,而不是一個3xx重定向響應。例如,返回一個HTML頁面,其中包含一個與重定向URI連結的動作的“繼續”按鈕。
客戶端必須忽略不能識別的響應引數,授權碼字串的長度本規範並未定義。客戶端應該避免對授權碼長度的猜測,授權伺服器應該記錄下所頒發的授權碼的長度。
4.2.2.1 錯誤響應(Error Response)
如果由於缺失、無效、不匹配重定向URI和客戶端識別符號,授權伺服器應該通知資源所有者錯誤,不能自動的重定向使用者代理到無效的重定向URI。
如果資源所有者拒絕客戶端的訪問請求,授權碼伺服器應該使用"application/x-www-form-urlencoded"格式新增下列引數到重定向URI的查詢元件(query component)中。
error:必須。一個簡單的、來自於包含下面引數的 ASCII 錯誤程式碼。
invalid_request(無效請求):請求缺少所需的引數,包括無效的引數值,其中包含一次以上的引數,或者是其他格式錯誤的。
unauthorized_client(未授權的客戶端):客戶端沒有授權使用此方法請求授權碼。
access_denied(訪問拒絕):資源所有者或者授權伺服器拒絕請求。
unsupported_response_type(不支援的響應型別):授權伺服器不支援使用此方法獲得授權程式碼。
invalid_scope(無效的請求範圍):請求的範圍無效、未知或格式錯誤。
server_error(伺服器錯誤):授權伺服器遇到意外情況,阻止它執行請求(因為當重定向時,一個500內部錯誤Http狀態碼不能返回給客戶端,所以這個錯誤碼是必須的。)。
temporarily_unavailable(暫時不可用):由於臨時伺服器超載或維護,授權伺服器目前無法處理請求。
error_description(錯誤的描述):可選。提供額外資訊,人類可讀的ASCII碼文字字串。幫助客戶端的開發者理解發生的錯誤。
error_uri(錯誤URI):可選。帶有錯誤資訊的且可讀的Web頁面,用於向客戶端開發人員提供關於錯誤的附加資訊。
state(狀態):可選。如果在客戶機授權請求中存在“state”引數,則需要原封不動的返回。
例如:授權伺服器通過傳送下面的Http 響應重定向使用者代理到客戶端。
HTTP/1.1 302 Found
Location: https://client.example.com/cb#error=access_denied&state=xyz
4.3 資源所有者密碼憑證許可型別(Resource Owner Password Credentials Grant)
只有當資源所有者充分信任(例如:客戶端是整個系統的一部分,或者是特權應用程式,或者其他授權許可不可用時)客戶端的情況下,才使用該模式。當使用該模式時,授權伺服器應該特別小心,並且只有在其他授權流不可用的情況下,才使用該模式。
此授權型別適用於能夠獲得資源所有者證書的客戶端(使用者名稱和密碼,通常使用互動式表單)。它還用於遷移現有客戶使用直接的認證方案,如HTTP基本或摘要通過將儲存的憑據來訪問令牌的OAuth認證。
+----------+
| Resource |
| Owner |
| |
+----------+
v
| Resource Owner
(A) Password Credentials
|
v
+---------+ +---------------+
| |>--(B)---- Resource Owner ------->| |
| | Password Credentials | Authorization |
| Client | | Server |
| |<--(C)---- Access Token ---------<| |
| | (w/ Optional Refresh Token) | |
+---------+ +---------------+
圖5:資源所有者密碼憑證流程
(A)資源所有者向客戶端提供使用者名稱和密碼。
(B)客戶端通過包含從資源所有者收到的憑據,請求來自授權伺服器令牌端點的訪問令牌。當發起請求時,客戶端與授權伺服器進行認證。
(C)授權伺服器認證客戶端,並驗證資源所有者憑證,如果有效,頒發一個訪問令牌。
4.3.1 授權請求和響應(Authorization Request And Response)
客戶機獲取資源所有者證書的方法超出了本規範的範圍。一旦訪問令牌獲得,客戶端必須丟棄憑據(理想狀態)。
4.3.2 訪問令牌請求(Access Token Request)
客戶端對令牌端點發送請求,並新增下列引數到查詢元件(query component)中(注意使用 "application/x-www-form-urlencoded" ),在在HTTP請求實體中使用utf-8字元編碼。
grant_type(授權許可型別):必須。值必須為“password” 。
username(使用者名稱):必須 。
password(密碼):必須。
scope(請求的範圍):可選
例如:客戶端使用TLS傳送下面的請求=>
POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded
grant_type=password&username=johndoe&password=A3ddj3w
授權伺服器必須:
- 如果客戶端是機密的,則授權伺服器必須認證客戶端。
- 如果客戶端憑證存在,則認證客戶端。
- 使用存在的密碼驗證策略,驗證資源所有者密碼憑證。
由於此訪問令牌請求使用資源所有者的密碼,授權伺服器必須保護端點不受暴力攻擊(例如使用速度限制、驗證碼、彈窗等等)。
4.3.4 訪問令牌響應(Access Token Response)
如果訪問令牌請求有效並已被授權,則授權服務需頒發一個必須的訪問令牌和一個可選的重新整理令牌。如果請求客戶端認證失敗或者無效,授權伺服器將返回錯誤的響應。
成功響應的例子:
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache {
"access_token":"2YotnFZFEjr1zCsicMWpAA",
"token_type":"example",
"expires_in":3600,
"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
"example_parameter":"example_value"
}
4.4 客戶端許可型別(Client Credentials Grant)
當客戶端僅僅想使用自己的憑證請求訪問受其控制的,或請求授權伺服器已經配置的另一個資源所有者的受保護資源。
客戶憑證許可型別必須僅由機密客端使用。
+---------+ +---------------+
| | | |
| |>--(A)- Client Authentication --->| Authorization |
| Client | | Server |
| |<--(B)---- Access Token ---------<| |
| | | |
+---------+ +---------------+ 圖 6: 客戶端憑證流程
(A)客戶端和授權伺服器進行認證,並向令牌端點請求訪問令牌。
(B)授權伺服器認證客戶端,如果,有效,則頒發訪問令牌。
4.4.1 授權請求和響應(Authorization Request And Response)
因為客戶端憑證被作為授權許可,所有不需要其他額外的授權請求。
4.4.2 訪問令牌請求(Access Token Request)
客戶端對令牌端點發送請求,並新增下列引數(注意使用 "application/x-www-form-urlencoded" 格式和utf-8字元編碼)在HTTP請求實體中。。
grant_type(授權許可型別):必須。值必須為“client_credentials” 。
scope(請求的範圍):可選
例如:客戶端使用TLS傳送下面的請求=>
POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded grant_type=client_credentials
授權伺服器必須認證客戶端。
4.4.4 訪問令牌響應(Access Token Response)
如果訪問令牌請求有效並已被授權,則授權服務需頒發一個必須的訪問令牌和一個可選的重新整理令牌。如果請求客戶端認證失敗或者無效,授權伺服器將返回錯誤的響應。
成功響應的例子:
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache {
"access_token":"2YotnFZFEjr1zCsicMWpAA",
"token_type":"example",
"expires_in":3600,
"example_parameter":"example_value"
}
4.5 擴充套件許可型別(Extension Grant)
通過與授權伺服器進行溝通,客戶端將授權伺服器定義好的授權許可型別的值作為引數“grant_type”的值,也可以包含其他的一些引數,向令牌端點發送請求。