開放授權協議OAuth2.0簡介
可能你跟我一樣,使用過各種第三方開放授權庫(如在你的 APP 中獲取 QQ 照片或微博評論等)來獲取用戶的一些資源,今天跟大家總結分享一下開放授權(OAuth2.0,1.0太復雜已經被棄用)的概念和原理,在以后使用開放授權SDK時能快速高效完成。
OAuth解決了什么問題?
OAuth 產生主要解決了第三方應用訪問用戶在某網站網絡資源的問題。例如,上圖中,用戶在36氪登陸時,可以用 QQ 來登陸,點擊用 QQ 登陸后,就出現了第三方應用36氪想獲取用戶基本的 QQ 信息已經微博評論,然后快速登陸的過程;再例如某個圖片網站想獲取你 QQ 空間的照片,那么就需要跟 QQ 申請獲取空間圖片的權限,而 QQ 會返回界面,讓用戶來選擇是否授權。
OAuth協議的角色
- Resource Owner(RO):資源所有者,在上面的例子中是 QQ 用戶。
- Resource Server(RS):資源服務器,在上面例子中是 QQ 微博評論和空間照片這兩個資源 Server,存儲并處理對這些資源的訪問。
- Authorization Server(AS):授權服務器,認證資源所有者身份并
根據 OAuth2.0 的 RFC 6749,其流程如下圖所示:
A. 用戶使用某應用后,此應用要求用戶授權訪問一些資源。例如第一幅圖中右下角所示 “36氪將獲取以下權限...”。
B. 用戶同意給此應用授權(Grant)。例如第一幅圖,用戶點擊 QQ 賬號確認。
C. 應用使用 B 步驟用戶的授權,向認證服務器(AS)申請訪問令牌(Access Token)。
D. 認證服務器(AS)驗證通過后,向應用返回訪問令牌(Access Token)。
E. 應用使用獲取到的訪問令牌,向資源服務器(RS)獲取資源。
F. 資源服務器驗證訪問令牌的有效性,驗證通過,給應用提供相應的資源。
OAuth2.0 提出多種授權類型來支持不同類型的第三方應用,有授權碼(Authorization Code Grant)、隱式授權 (Implicit Grant)、RO憑證授權 (Resource Owner Password Credentials Grant)、Client憑證授權 (Client Credentials Grant), 我們只看最廣泛使用的、功能最完整嚴密的授權碼模式。其他可以參考 RFC 6749。
授權碼模式
如下圖所示,授權碼模式如下:
A. 用戶訪問應用,應用將用戶引向認證服務器。如第一幅圖,36氪想獲取QQ用戶一些資源,首先將用戶引向QQ的授權頁面(授權服務器返回)。
應用申請認證的 URL,可包含以下參數:
- response_type:這個值必須是 "code",用于獲取授權碼(authorization code);必選。
- client_id:應用的 ID 名稱;必選。
- redirect_uri:重定向鏈接;可選。
- scope:應用申請權限的范圍;可選。
- state:當前應用狀態,應用可指定任意值,AS返回此值,主要用于抵制 CSRF 攻擊;可選。
B. 用戶在授權服務器返回的頁面上選擇是否給予此應用授權(用戶必須顯式同意或拒絕)。如第一幅圖,QQ授權服務器返回一個界面,有36氪想獲取的資源,用戶來決定是否給予這些授權。
C. 如果用戶同意授權,認證服務器將用戶轉向應用已經指定的 重定向鏈接(redirection URI),重定向鏈接包必須含一個授權碼(authorization_code);不同意則通過 重定向鏈接(redirection URI) 返回對應的 ERROR 信息。
認證服務器返回給應用的 URI,需要包含的參數如下:
- code: AS產生的授權碼,為了安全起見,授權碼的有效期一般為10分鐘,應用拿到后只能使用一次;多余一次 AS 拒絕服務。授權碼與應用 ID 以及重定向 URL 一一對應;必選。
- state: 若應用的請求中包含這個參數,認證服務器的回應也必須一模一樣包含這個參數,主要為了抵制 CSRF 攻擊;必選。
認證服務器返回 ERROR 信息,主要包含:
- error: 一個 ASCII 編碼的 error code,其值意義包括 invalid_request、unauthorized_client、access_denied、 unsupported_response_type、invalid_scope、server_error、 temporarily_unavailable;必選。
- error_description:對錯誤的描述;可選。
- error_uri:對于錯誤的附加信息,比如出現了這個錯誤,然后指向錯誤的幫助頁面;可選。
- state:state值如果應用請求的信息里有,必須給予相同值的回復;必選。
D. 應用收到授權碼,加上之前的重定向鏈接和認證應用身份的數據,訪問認證服務器(AS)來獲取授權令牌(Access Token)。
應用向認證服務器申請訪問令牌的HTTP請求,包含以下參數
- grant_type:值必須是 "authorization_code";必選。
- code:認證服務器返回的授權碼;必選。
- redirect_uri:表示重定向 URI,且必須與A步驟中的該參數值保持一致;必選。
- client_id:表示應用ID;必選項。
E. 認證服務器收到 D 中的數據后,首先驗證應用合法性,其次驗證 redirect_uri 與 C 中的是否一致,驗證通過后,返回授權令牌。
認證服務器發送的HTTP回復,包含以下參數:
-
access_token:表示訪問令牌;必選項。
-
token_type:令牌類型,該值大小寫不敏感,可以是 bearer 類型或 mac 類型;必選項。
-
expires_in:過期時間,單位為秒。如果省略該參數,必須其他方式設置過期時間;推薦使用。
-
refresh_token:更新令牌,用來獲取下一次的訪問令牌,可選項。
-
scope:權限范圍,如果與客戶端申請的范圍一致,可省略此項。
舉例說明授權碼模式
這個例子是The OAuth 2.0 Authorization Framework-RFC6749上的。
與授權碼模式的 A B C D E 分別對應。
A
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
B
用戶選擇同意還是拒絕,這里沒有產生動作。
C
HTTP/1.1 302 Found Location: https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA&state=xyz
ERROR 時返回:
HTTP/1.1 302 Found Location: https://client.example.com/cb#error=access_denied&state=xyz
D
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
E
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" }
還可以參考第三方開放授權的文檔,比如 QQ,新浪微博等,都有對他們自己開放授權 SDK 的詳細介紹。
來自:http://stackvoid.com/introduce-to-oath2.0/