OAuth 2.0 協(xié)議原理詳解

      網(wǎng)友投稿 894 2022-05-30

      OAuth 2.0 是目前比較流行的做法,它率先被Google, Yahoo, Microsoft, Facebook等使用。之所以標(biāo)注為 2.0,是因為最初有一個1.0協(xié)議,但這個1.0協(xié)議被弄得太復(fù)雜,易用性差,所以沒有得到普及。2.0是一個新的設(shè)計,協(xié)議簡單清晰,但它并不兼容1.0,可以說與1.0沒什么關(guān)系。所以,我就只介紹2.0。

      協(xié)議的參與者

      從引言部分的描述我們可以看出,OAuth的參與實(shí)體至少有如下4個:

      RO (resource owner): 資源所有者,對資源具有授權(quán)能力的人。如上文中的用戶Alice。

      RS (resource server): 資源服務(wù)器,它存儲資源,并處理對資源的訪問請求。如Google資源服務(wù)器,它所保管的資源就是用戶Alice的照片。

      Client: 第三方應(yīng)用,它獲得RO的授權(quán)后便可以去訪問RO的資源。如網(wǎng)易印像服務(wù)。

      AS (authorization server): 授權(quán)服務(wù)器,它認(rèn)證RO的身份,為RO提供授權(quán)審批流程,并最終頒發(fā)授權(quán)令牌(Access Token)。讀者請注意,為了便于協(xié)議的描述,這里只是在邏輯上把AS與RS區(qū)分開來;在物理上,AS與RS的功能可以由同一個服務(wù)器來提供服務(wù)。

      授權(quán)類型

      在開放授權(quán)中,第三方應(yīng)用(Client)可能是一個Web站點(diǎn),也可能是在瀏覽器中運(yùn)行的一段JavaScript代碼,還可能是安裝在本地的一個應(yīng)用程序。這些第三方應(yīng)用都有各自的安全特性。對于Web站點(diǎn)來說,它與RO瀏覽器是分離的,它可以自己保存協(xié)議中的敏感數(shù)據(jù),這些密鑰可以不暴露給RO;對于javascript代碼和本地安全的應(yīng)用程序來說,它本來就運(yùn)行在RO的瀏覽器中,RO是可以訪問到Client在協(xié)議中的敏感數(shù)據(jù)。

      OAuth為了支持這些不同類型的第三方應(yīng)用,提出了多種授權(quán)類型,如:

      授權(quán)碼 (Authorization Code Grant)

      隱式授權(quán) (Implicit Grant)

      RO憑證授權(quán) (Resource Owner Password Credentials Grant)

      Client憑證授權(quán) (Client Credentials Grant)

      由于本文旨在幫助用戶理解OAuth協(xié)議,所以我將先介紹這些授權(quán)類型的基本思路,然后選擇其中最核心、最難理解、也是最廣泛使用的一種授權(quán)類型——“授權(quán)碼”,進(jìn)行深入的介紹。

      2.1 授權(quán)碼模式

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

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

      OAuth 2.0 協(xié)議原理詳解

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

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

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

      2.2 隱授權(quán)模式(implicit grant type)

      User-Agent適用于客戶端不能保存客戶端私有證書的App(純客戶端App,無Server參與)。因為純客戶端的程序不能保存密鑰

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

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

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

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

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

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

      2.3 密碼模式

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

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

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

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

      2.4 客戶端模式

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

      (A)客戶端向認(rèn)證服務(wù)器進(jìn)行身份認(rèn)證,并要求一個訪問令牌。

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

      授權(quán)碼模式的實(shí)例化描述

      面我以實(shí)例化方式來幫助讀者理解授權(quán)碼類型的授權(quán)協(xié)議的運(yùn)行過程。假設(shè):

      (1) Alice有一個有效的Google帳號;

      (2) Facebook.com已經(jīng)在Google Authorization Server上注冊了Client身份,已經(jīng)獲得(client_id, client_secret),注意client_secret是Client與AS之間的一個共享密鑰。

      (3) Alice想授權(quán)Facebook.com查看她的聯(lián)系人列表(https://www.google.com/m8/feeds)。

      下圖展示了Alice、Facebook.com、Google資源服務(wù)器、以及Google OAuth授權(quán)服務(wù)器之間的協(xié)議運(yùn)行過程。

      協(xié)議所涉及到的細(xì)節(jié)都已經(jīng)在圖上了,所以不打算再做詳細(xì)介紹了。若看懂了此圖,OAuth2.0就理解了。

      讀者請注意,在步驟(4)中,Client需要拿“授權(quán)碼”去換“授權(quán)令牌”時,Client需要向AS證明自己的身份,即證明自己就是步驟(2)中Alice批準(zhǔn)授權(quán)時的Grantee。這個身份證明的方法主要有兩種(圖3中使用了第1種):

      (1) 通過https直接將client_secret發(fā)送給AS,因為client_secret是由Client與AS所共享,所以只要傳送client_secret的信道安全即可。

      (2) 通過消息認(rèn)證碼來認(rèn)證Client身份,典型的算法有HMAC-SHA1。在這種方式下,Client無需傳送client_secret,只需發(fā)送消息請求的signature即可。由于不需要向AS傳遞敏感數(shù)據(jù),所以它只需要使用http即可。

      此外, 在步驟(2)中,Google授權(quán)服務(wù)器需要認(rèn)證Alice的RO身份,并提供授權(quán)界面給Alice進(jìn)行授權(quán)審批。今天Google提供的實(shí)例如下圖所示,僅供讀者理解OAuth這種“現(xiàn)場授權(quán)”或”在線授權(quán)”的含義。

      OAuth2.0授權(quán)類型選擇

      授權(quán)模式實(shí)際上就是指獲取token的方法,選擇授權(quán)模式主要取決于最終用戶使用的客戶端的類型,以及你服務(wù)對用戶的表現(xiàn)形式。

      具體的選擇方式如下圖:

      First Party or third party client?

      First party指的是,你完全信任這個客戶端可以管理好最終用戶的認(rèn)證憑據(jù)。比如說對于Spotify的開發(fā)者和所有者來說,他們完全信任他們的Spotify iphone客戶端。而third party客戶端是指我們不信任的客戶端。

      Access Token Owner?

      Access Token表示給一個客戶端授權(quán)訪問某些被保護(hù)的資源。如果我們只需要給一個機(jī)器授權(quán)訪問某些資源,而不需要給人授權(quán),那么這些資源應(yīng)該實(shí)現(xiàn)client credential grant。

      如果我們需要給人授權(quán)訪問資源,那么需要視客戶端的類型做決定。

      Client type?

      客戶端類型主要是指客戶端是否有能力保存秘鑰。

      如果客戶端是個web app,并且有服務(wù)器側(cè)的組件,那么我們應(yīng)該選擇authorization code grant

      如果客戶端是一個純前端的web app(如:單頁面應(yīng)用),如果客戶端可信,我們可以選擇password grant,如果客戶端不可信可以選擇implicit grant

      如果客戶端是一個本地應(yīng)用,比如一個手機(jī)app,應(yīng)該選擇password grant。

      第三方本地應(yīng)用應(yīng)該用authorization code grant(通過本地瀏覽器,不要用嵌入式瀏覽器,比如iOS強(qiáng)制用戶用Safari或者SFSafariViewController,而不用 WKWebView)。

      OAuth設(shè)計上的安全性考慮

      為何引入authorization_code?

      協(xié)議設(shè)計中,為什么要使用authorization_code來交換access_token?這是讀者容易想到的一個問題。也就是說,在協(xié)議的第3步,為什么不直接將access_token通過重定向方式返回給Client呢?比如:

      12345

      HTTP/1.1?302Location:https://www.facebook.com/?access_token=ya29.AHES6ZSXVKYTW2VAGZtnMjD&token_type=Bearer&expires_in=3600

      如果直接返回access_token,協(xié)議將變得更加簡潔,而且少一次Client與AS之間的交互,性能也更優(yōu)。那為何不這么設(shè)計呢?協(xié)議文檔[1]中并沒有給出這樣設(shè)計的理由,但也不難分析:

      (1) 瀏覽器的redirect_uri是一個不安全信道,此方式不適合于傳遞敏感數(shù)據(jù)(如access_token)。因為uri可能通過HTTP referrer被傳遞給其它惡意站點(diǎn),也可能存在于瀏覽器cacher或log文件中,這就給攻擊者盜取access_token帶來了很多機(jī)會。另外,此協(xié)議也不應(yīng)該假設(shè)RO用戶代理的行為是可信賴的,因為RO的瀏覽器可能早已被攻擊者植入了跨站腳本用來監(jiān)聽access_token。因此,access_token通過RO的用戶代理傳遞給Client,會顯著擴(kuò)大access_token被泄露的風(fēng)險。 但authorization_code可以通過redirect_uri方式來傳遞,是因為authorization_code并不像access_token一樣敏感。即使authorization_code被泄露,攻擊者也無法直接拿到access_token,因為拿authorization_code去交換access_token是需要驗證Client的真實(shí)身份。也就是說,除了Client之外,其他人拿authorization_code是沒有用的。 此外,access_token應(yīng)該只頒發(fā)給Client使用,其他任何主體(包括RO)都不應(yīng)該獲取access_token。協(xié)議的設(shè)計應(yīng)能保證Client是唯一有能力獲取access_token的主體。引入authorization_code之后,便可以保證Client是access_token的唯一持有人。當(dāng)然,Client也是唯一的有義務(wù)需要保護(hù)access_token不被泄露。

      (2) 引入authorization_code還會帶來如下的好處。由于協(xié)議需要驗證Client的身份,如果不引入authorization_code,這個Client的身份認(rèn)證只能通過第1步的redirect_uri來傳遞。同樣由于redirect_uri是一個不安全信道,這就額外要求Client必須使用數(shù)字簽名技術(shù)

      來進(jìn)行身份認(rèn)證,而不能用簡單的密碼或口令認(rèn)證方式。引入authorization_code之后,AS可以直接對Client進(jìn)行身份認(rèn)證(見步驟4和5),而且可以支持任意的Client認(rèn)證方式(比如,簡單地直接將Client端密鑰發(fā)送給AS)。

      在我們理解了上述安全性考慮之后,讀者也許會有豁然開朗的感覺,懂得了引入authorization_code的妙處。那么,是不是一定要引入authorization_code才能解決這些安全問題呢?當(dāng)然不是。筆者將會在另一篇博文給出一個直接返回access_token的擴(kuò)展授權(quán)類型解決方案,它在滿足相同安全性的條件下,使協(xié)議更簡潔,交互次數(shù)更少。

      一切只是看上去很美好,但其實(shí)很多坑

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

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

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

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

      攻擊者使用自己的賬戶申請第三方授權(quán)登陸

      授權(quán)后服務(wù)端返回授權(quán)碼,但是此時組織授權(quán)回跳,此時Client并沒有接到授權(quán)碼,也就是阻斷了授權(quán)流程

      攻擊者將此跳轉(zhuǎn)鏈接發(fā)給一個正在處于在Client登陸狀態(tài)的賬戶

      誘騙正常用戶點(diǎn)擊,那么此時攻擊者第三方賬戶和被攻擊賬戶進(jìn)行綁定(相當(dāng)于賬戶綁定了第三方的賬戶)

      攻擊者再次進(jìn)行第三方授權(quán)登陸。這樣就劫持了誘騙的賬戶。轉(zhuǎn)賬?刪好友?等等就所以搞了。

      解決辦法:

      在進(jìn)行授權(quán)碼申請或者是Token申請的時候帶上state參數(shù),服務(wù)器返回請求時要求攜帶state參數(shù),在Client處理授權(quán)的時候校驗此參數(shù)。參數(shù)可以是當(dāng)前賬戶的SessionId,或Cookie的簽名串。在Client申請accessToken會驗證相關(guān)state和當(dāng)前用戶的關(guān)系,這樣就防止了篡改。

      OAuth的校驗流程為什么這么復(fù)雜,直接授權(quán)之后redirect回accessToken不就結(jié)了嗎?為什么還要返回auth_code之后請求accessToken?

      首先,redirect是不安全的,隨時可以暫停回調(diào)而拿到accessToken,拿到了accessToken也就意味著拿到了授權(quán),但是auth_code是和client相對應(yīng)的,那么即使拿到了auth_code還需要再次申請accessToken,申請accessToken時需要校驗Client和state。同時協(xié)議設(shè)計的原則就是只有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

      人人網(wǎng)OAuth歷程:http://www.infoq.com/cn/presentations/dx-renren-authentication-authorization/

      通用安全

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:sql用逗號連接多張表對應(yīng)哪個join?
      下一篇:nunjucks:繼承與jinja2的js模板引擎
      相關(guān)文章
      久久99亚洲网美利坚合众国| 伊人亚洲综合青草青草久热| 亚洲国产人成网站在线电影动漫| 亚洲国产成人乱码精品女人久久久不卡| 亚洲国产日韩在线成人蜜芽| 99亚洲精品高清一二区| 亚洲国产精彩中文乱码AV| 亚洲精品无码久久久久sm| 亚洲精品国产精品乱码不卡√| 国产亚洲精品不卡在线| 中文国产成人精品久久亚洲精品AⅤ无码精品 | 亚洲av无码潮喷在线观看| 亚洲乱码一区二区三区在线观看| 区久久AAA片69亚洲| 亚洲乱码精品久久久久..| 国产亚洲精品无码成人| 亚洲VA中文字幕无码一二三区| 亚洲VA中文字幕无码一二三区 | 亚洲国产一成人久久精品| 亚洲AV中文无码乱人伦下载 | 亚洲一区二区三区首页| 久久亚洲精品无码aⅴ大香| 亚洲色图综合网站| 亚洲三级视频在线观看| 中文字幕亚洲综合久久综合| 亚洲精品蜜夜内射| 亚洲av日韩av欧v在线天堂| 亚洲一区精品伊人久久伊人| 亚洲男人的天堂www| 亚洲AV日韩精品久久久久| 亚洲精品在线免费观看| 亚洲精品二三区伊人久久| 亚洲精品人成网线在线播放va | 亚洲精品美女在线观看| 91丁香亚洲综合社区| 亚洲人成色777777老人头| 五月婷婷亚洲综合| 亚洲综合精品香蕉久久网| 婷婷亚洲综合五月天小说| 亚洲图片中文字幕| 亚洲国产精品ⅴa在线观看|