OAuth2.0原理和驗證流程分析

什么是三方授權?

第三方授權就是,委托第三方來對既定的用戶進行鑒定,鑒定成功之后,下發信任憑證,信任憑證和用戶掛鉤,同時可以使用此憑證來去第三方平臺,獲得該用戶開放的部分信息.
直白的說,就是將用戶授權的工作交給第三方來做,而自己只維護信任憑證,并且獲取用戶信息。就像我們的QQ和微博一樣,你在逛各大論壇的時候,總會有一種途徑就是第三方的App登陸。顯然這種驗證是要在第三方做的,而論壇只需要維護一個token,并且可以獲取你的個人信息,然而沒什么軟用。你如果想用部分功能,還是得注冊,因為你相當于論壇只是一個有部分信息的游客,而沒有成為它的用戶,這種手段可以看成是提高自己訪問量或轉化率的一種手段吧。其實這種授權方案不一樣只用在互聯網,部分企業級的網站做資源的共享訪問也是這么做的。比如兩個網站合作,A站點賬戶可以登陸B站點,B站點賬戶可以登陸A站點,這樣A站點就能拿到B站點相關資源,反過來也是。就做到了資源共享。
那么這種授權是怎么做的呢?到底安全不安全?那么可能就要引出OAuth協議了。

OAuth是怎么做的#####

首先OAuth只是一個授權協議,不是一個實現或是一個中間件。
OAuth1于2007年10月建立,之后又在2009年6月重新修訂和發布 http://oauth.net/core/1.0a/
OAuth1.0授權流程是什么?

Paste_Image.png

流程很復雜,因為OAuth需要保證授權碼和Token在傳輸的時候不被截取和篡改,所以使用了很多簽名反復的驗證。
OAuth1.0的問題:
反復的簽名,開放平臺本來就面對開發者,但是反復的簽名導致開發的流程太過于復雜。
沒有引入回跳地址的判斷,導致會跳可能會篡改,這樣授權碼和Token會被Hack掉(1.0a的時候修復了這個漏洞)。
授權流程過于單一化。

OAuth2.0的引入:
抽象驗證流程
由于OAuth1過于復雜,之后對OAuth進行了改造引入了Oauth2.0。OAuth的授權過程如下:

Paste_Image.png

(A) 客戶端從資源擁有者那里請求授權。授權請求能夠直接發送給資源擁有者,或者間接地通過授權服務器這樣的中介,而后者更為可取。

(B) 客戶端收到一個訪問許可,它代表由資源服務器提供的授權。

(C) 客戶端使用它自己的私有證書到授權服務器上驗證,并出示訪問許可,來請求一個訪問令牌。

(D) 授權服務器驗證客戶端私有證書和訪問許可的有效性,如果驗證通過則分發一個訪問令牌。

(E) 客戶端通過出示訪問令牌向資源服務器請求受保護資源。

(F) 資源服務器驗證訪問令牌的有效性,如果驗證通過則響應這個資源請求。

上面只是一個抽象的驗證流程,根據上面的抽象流程演化出四種驗證模式:
授權碼模式
授權碼模式和上述的 抽象驗證模式流程比較相似:

Paste_Image.png

(A) web客戶端通過將終端用戶的user-agent重定向到授權服務器來發起這個流程。客戶端傳入它的客戶端標識符、請求作用域、本地狀態和一個重定向URI,在訪問被許可(或被拒絕)后授權服務器會重新將終端用戶引導回這個URI。

(B) 授權服務器驗證終端用戶(借助于user-agent),并確定終端用戶是否許可客戶端的訪問請求。

(C) 假定終端用戶許可了這次訪問,授權服務器會將user-agent重定向到之前提供的重定向URI上去。授權服務器為客戶端傳回一個授權碼做獲取訪問令牌之用。

(D) 客戶端通過驗證并傳入上一步取得的授權碼從授權服務器請求一個訪問令牌。(需要帶上ClientId和Secret,ClientId和Secret是通過平臺授予)

(E) 授權服務器驗證客戶端私有證書和授權碼的有效性并返回訪問令牌。

授權碼模式(implicit grant type)
User-Agent子態適用于客戶端不能保存客戶端私有證書的App(純客戶端App,無Server參與)。因為可純客戶端的程序不能保存密鑰

Paste_Image.png

(A) 客戶端將user-agent引導到終端用戶授權endpoint。客戶端傳入它的客戶端標識符、請求作用域、本地狀態和一個重定向URI,在訪問被許可(或被拒絕)后授權服務器會重新將終端用戶引導回這個URI。

(B) 授權服務器驗證終端用戶(通過user-agent)并確認終端用戶是許可還是拒絕了客戶端的訪問請求。

(C) 如果終端用戶許可了這次訪問,那么授權服務器會將user-agent引導到之前提供的重定向URI。重定向URI會在URI片斷{譯者注:URI片斷是指URI中#號之后的內容}中包含訪問令牌。

(D) user-agent響應重定向指令,向web服務器發送不包含URI片斷的請求。user-agent在本地保存URI片斷。

(E) web服務器返回一個web頁面(通常是嵌入了腳本的HTML網頁),這個頁面能夠訪問完整的重定向URI,它包含了由user-agent保存的URI片斷,同時這個頁面能夠將包含在URI片斷中的訪問令牌(和其它參數)提取出來。

(F) user-agent在本地執行由web服務器提供的腳本,該腳本提取出訪問令牌并將它傳遞給客戶端。

密碼模式
密碼模式就是將密碼托管給第三方App,但是必須要保證第三方App高度可信。

Paste_Image.png

(A)用戶向客戶端提供用戶名和密碼。

(B)客戶端將用戶名和密碼發給認證服務器,向后者請求令牌。

(C)認證服務器確認無誤后,向客戶端提供訪問令牌。

客戶端模式
這種模式不需要終端用戶的參與,只是Client和Server端的交互。通常只用于Client狀態的獲取。

Paste_Image.png

(A)客戶端向認證服務器進行身份認證,并要求一個訪問令牌。

(B)認證服務器確認無誤后,向客戶端提供訪問令牌。

授權流程
這里以授權碼方式流程說明,主要流程分為兩步,獲取授權碼和通過授權碼獲取資源票據:

Paste_Image.png
Paste_Image.png

(A)用戶訪問客戶端,后者將前者導向認證服務器。

(B)用戶選擇是否給予客戶端授權。

(C)假設用戶給予授權,認證服務器將用戶導向客戶端事先指定的"重定向URI"(redirection URI),同時附上一個授權碼。

(D)客戶端收到授權碼,附上早先的"重定向URI",向認證服務器申請令牌。這一步是在客戶端的后臺的服務器上完成的,對用戶不可見。

(E)認證服務器核對了授權碼和重定向URI,確認無誤后,向客戶端發送訪問令牌(access token)和更新令牌(refresh token)。

A步驟中,客戶端申請認證的URI,包含以下參數:

response_type:表示授權類型,必選項,此處的值固定為"code"
client_id:表示客戶端的ID,必選項
redirect_uri:表示重定向URI,可選項
scope:表示申請的權限范圍,可選項
state:表示客戶端的當前狀態,可以指定任意值,認證服務器會原封不動地返回這個值。


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

C步驟中,服務器回應客戶端的URI,包含以下參數:
code:表示授權碼,必選項。該碼的有效期應該很短,通常設為10分鐘,客戶端只能使用該碼一次,否則會被授權服務器拒絕。該碼與客戶端ID和重定向URI,是一一對應關系。
state:如果客戶端的請求中包含這個參數,認證服務器的回應也必須一模一樣包含這個參數。


HTTP/1.1 302 Found
Location: https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA
          &state=xyz

D步驟中,客戶端向認證服務器申請令牌的HTTP請求,包含以下參數:
grant_type:表示使用的授權模式,必選項,此處的值固定為"authorization_code"。
code:表示上一步獲得的授權碼,必選項。
redirect_uri:表示重定向URI,必選項,且必須與A步驟中的該參數值保持一致。
client_id:表示客戶端ID,必選項。


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回復,包含以下參數:
access_token:表示訪問令牌,必選項。
token_type:表示令牌類型,該值大小寫不敏感,必選項,可以是bearer類型或mac類型。
expires_in:表示過期時間,單位為秒。如果省略該參數,必須其他方式設置過期時間。
refresh_token:表示更新令牌,用來獲取下一次的訪問令牌,可選項。
scope:表示權限范圍,如果與客戶端申請的范圍一致,此項可省略。

 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"
     }

資源訪問過程:
http://localhost:8082/oauth/server/resource/uname.do?access_token=233730a3d4cdc1af64f78fa80bc13c6e
此處主要由資源服務方實現,對于access_token進行校驗。

token過期刷新過程:
客戶端使用“refresh_token”訪問許可類型和下列參數傳入刷新令牌:
refresh_token:
必需參數。與待刷新的訪問令牌相關聯的刷新令牌。
grant_type=refresh_token&client_id=s6BhdRkqt3&client_secret=8eSEIpnqmM&refresh_token=n4E9O119d
授權服務器必須驗證客戶端私有證書(如果存在),驗證刷新令牌是否有效,以及驗證資源擁有者的授權是否仍然有效。如果請求有效,授權服務器則發布一個訪問令牌響應,原來的Token失效。以后訪問必須使用新Token。

一切只是看上去很美好,但其實很多坑####

OAuth2看上去很美好,但是細心觀察其實還是有一些漏洞的。

  1. 對于授權碼和access_token的篡改,在OAuth1中是反復的對Code和Token進行簽名,來保證Token不會被篡改,但是OAuth2中卻沒有,因為OAuth2是基于Https的,所以如果沒有Https的支持OAuth2可能還不如OAuth1.

  2. 對于redirect_uri的校驗,OAuth1中沒有提到redirect_uri的校驗,那么OAuth2中要求進行redirect_uri的校驗。但是如果校驗規則過松,也會導致跳轉的安全問題。 例如:校驗的時候只校驗根域名,或者二級域名,但是第三方App對自己的域名保護的不好,導致二級域名被hack那么此時授權碼和Token會被竊取。 校驗規則不嚴謹,例如www.baidu.com 但是redirect_uri為:www.a.com.\www.baidu.com,這樣授權就被a.com釣走了。

  3. 對于CSRF攻擊(跨站請求偽造):由于這個授權過程服務器和Client和用戶之間有幾次交互,但是在得到授權碼的時候需要一次回跳,但是這次回跳是可以被阻塞的。

  4. 攻擊者使用自己的賬戶申請第三方授權登陸

  5. 授權后服務端返回授權碼,但是此時組織授權回跳,此時Client并沒有接到授權碼,也就是阻斷了授權流程

  6. 攻擊者將此跳轉鏈接發給一個正在處于在Client登陸狀態的賬戶

  7. 誘騙正常用戶點擊,那么此時攻擊者第三方賬戶和被攻擊賬戶進行綁定(相當于賬戶綁定了第三方的賬戶)

  8. 攻擊者再次進行第三方授權登陸。這樣就劫持了誘騙的賬戶。轉賬?刪好友?等等就所以搞了。
    解決辦法:
    在進行授權碼申請或者是Token申請的時候帶上state參數,服務器返回請求時要求攜帶state參數,在Client處理授權的時候校驗此參數。參數可以是當前賬戶的SessionId,或Cookie的簽名串。在Client申請accessToken會驗證相關state和當前用戶的關系,這樣就防止了篡改。

  9. OAuth的校驗流程為什么這么復雜,直接授權之后redirect回accessToken不就結了嗎?為什么還要返回auth_code之后請求accessToken?
    首先,redirect是不安全的,隨時可以暫停回調而拿到accessToken,拿到了accessToken也就意味著拿到了授權,但是auth_code是和client相對應的,那么即使拿到了auth_code還需要再次申請accessToken,申請accessToken時需要校驗Client和state。同時協議設計的原則就是只有Client能拿到accessToken而用戶是拿不到的。

最后,切記HTTPS####

參考資料:
http://blog.csdn.net/seccloud/article/details/8192707
http://www.justwinit.cn/post/8138/
https://blog.yorkxin.org/2013/09/30/oauth2-1-introduction
人人網OAuth歷程:http://www.infoq.com/cn/presentations/dx-renren-authentication-authorization/

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,936評論 6 535
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,744評論 3 421
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,879評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,181評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,935評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,325評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,384評論 3 443
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,534評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,084評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,892評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,067評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,623評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,322評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,735評論 0 27
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,990評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,800評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,084評論 2 375

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,799評論 18 139
  • OAuth是一個關于授權(authorization)的開放網絡標準,在全世界得到廣泛應用,目前的版本是2.0版。...
    常曉曉閱讀 782評論 0 0
  • OAuth是一個關于授權(authorization)的開放網絡標準,在全世界得到廣泛應用,目前的版本是2.0版。...
    謝謝寫閱讀 753評論 0 1
  • OAuth是一個關于授權(authorization)的開放網絡標準,在全世界得到廣泛應用,目前的版本是2.0版。...
    夕望有你閱讀 291評論 1 2
  • 蘋果的遠程推送APNS: 原理過程什么的就不說了,這里主要是為了記錄一下今天解決推送所遇到的坑。 步驟主要分為四部...
    飛天江郎閱讀 1,869評論 2 2