深入理解OAuth2.0協(xié)議

1. 引言

如果你開車去酒店赴宴舒裤,你經(jīng)常會苦于找不到停車位而耽誤很多時間。是否有好辦法可以避免這個問題呢?有的撬统,聽說有一些豪車的車主就不擔(dān)心這個問題。豪車一般配備兩種鑰匙:主鑰匙和泊車鑰匙敦迄。當(dāng)你到酒店后恋追,只需要將泊車鑰匙交給服務(wù)生,停車的事情就由服務(wù)生去處理罚屋。與主鑰匙相比苦囱,這種泊車鑰匙的使用功能是受限制的:它只能啟動發(fā)動機并讓車行駛一段有限的距離,可以鎖車脾猛,但無法打開后備箱撕彤,無法使用車內(nèi)其他設(shè)備。這里就體現(xiàn)了一種簡單的“開放授權(quán)”思想:通過一把泊車鑰匙猛拴,車主便能將汽車的部分使用功能(如啟動發(fā)動機羹铅、行駛一段有限的距離)授權(quán)給服務(wù)生。

授權(quán)是一個古老的概念愉昆,它是一個多用戶系統(tǒng)必須支持的功能特性职员。比如,Alice和Bob都是Google的用戶跛溉,那么Alice應(yīng)該可以將自己的照片授權(quán)給Bob訪問焊切。但請注意到,這種授權(quán)是一種封閉授權(quán)芳室,它只支持系統(tǒng)內(nèi)部用戶之間的相互授權(quán)专肪,而不能支持與其他外部系統(tǒng)或用戶之間的授權(quán)。比如說堪侯,Alice想使用“網(wǎng)易印像服務(wù)”將她的部分照片沖印出來牵祟,她怎么能做到呢?

肯定有人會說抖格,Alice可以將自己的Google用戶名和密碼告訴網(wǎng)易印像服務(wù)诺苹,事情不就解決了嗎?是的雹拄,但只有毫不關(guān)注安全和隱私的同學(xué)才會出此“絕招”收奔。那么我們就來想一想,這一“絕招”存在哪些問題滓玖?(1) 網(wǎng)易印像服務(wù)可能會緩存Alice的用戶名和密碼坪哄,而且可能沒有加密保護。它一旦遭到攻擊,Alice就會躺著中槍翩肌。(2) 網(wǎng)易印像服務(wù)可以訪問Alice在Google上的所有資源模暗,Alice無法對他們進行最小的權(quán)限控制,比如只允許訪問某一張照片念祭,1小時內(nèi)訪問有效兑宇。(3) Alice無法撤消她的單個授權(quán),除非Alice更新密碼粱坤。

在以Web服務(wù)為核心的云計算時代隶糕,像用戶Alice的這種授權(quán)需求變得日益迫切與興盛,“開放授權(quán)(Open Authorization)”也正因此而生站玄,意在幫助Alice將她的資源授權(quán)給第三方應(yīng)用枚驻,支持細粒度的權(quán)限控制,并且不會泄漏Alice的密碼或其它認證憑據(jù)株旷。

根據(jù)應(yīng)用場景的不同再登,目前實現(xiàn)開放授權(quán)的方法分為兩種:一種是使用OAuth協(xié)議[1];另一種是使用IAM服務(wù)[2]晾剖。OAuth協(xié)議主要適用于針對個人用戶對資源的開放授權(quán)锉矢,比如Google的用戶Alice。OAuth的特點是“現(xiàn)場授權(quán)”或“在線授權(quán)”:客戶端主要通過瀏覽器去訪問資源钞瀑,授權(quán)時需要認證Alice的資源所有者身份沈撞,并且需要Alice現(xiàn)場審批。OAuth一般在SNS服務(wù)中廣泛使用雕什,如微博缠俺。IAM服務(wù)則不同,它的特點是“預(yù)先授權(quán)”或“離線授權(quán)”:客戶端主要通過REST API方式去訪問資源贷岸,資源所有者可以預(yù)先知道第三方應(yīng)用所需要的資源請求壹士,一次授權(quán)之后,很少會變更偿警。IAM服務(wù)一般在云計算服務(wù)中使用躏救,如AWS服務(wù)、阿里云計算服務(wù)螟蒸。

本文主要介紹OAuth開放授權(quán)盒使。關(guān)于以IAM服務(wù)提供的開放授權(quán),我將在另一篇博文中介紹七嫌。下面我來介紹OAuth 2.0協(xié)議少办、協(xié)議的實例化描述、安全性分析诵原。

2. OAuth 2.0 協(xié)議

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懈叹。

2.1 協(xié)議的參與者

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

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

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

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

此外,為了支持開放授權(quán)功能以及更好地描述開放授權(quán)協(xié)議饼煞,OAuth引入了第四個參與實體:

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

2.2 授權(quán)類型

在開放授權(quán)中振坚,第三方應(yīng)用(Client)可能是一個Web站點,也可能是在瀏覽器中運行的一段JavaScript代碼逃片,還可能是安裝在本地的一個應(yīng)用程序屡拨。這些第三方應(yīng)用都有各自的安全特性只酥。對于Web站點來說,它與RO瀏覽器是分離的呀狼,它可以自己保存協(xié)議中的敏感數(shù)據(jù)裂允,這些密鑰可以不暴露給RO;對于JavaScript代碼和本地安全的應(yīng)用程序來說哥艇,它本來就運行在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)碼”作媚,進行深入的介紹。

2.3 OAuth協(xié)議 - 基本思路

如圖1所示帅刊,協(xié)議的基本流程如下:


(1) Client請求RO的授權(quán)纸泡,請求中一般包含:要訪問的資源路徑,操作類型赖瞒,Client的身份等信息女揭。

(2) RO批準(zhǔn)授權(quán),并將“授權(quán)證據(jù)”發(fā)送給Client冒黑。至于RO如何批準(zhǔn)田绑,這個是協(xié)議之外的事情。典型的做法是抡爹,AS提供授權(quán)審批界面掩驱,讓RO顯式批準(zhǔn)。這個可以參考下一節(jié)實例化分析中的描述冬竟。

(3) Client向AS請求“訪問令牌(Access Token)”欧穴。此時,Client需向AS提供RO的“授權(quán)證據(jù)”泵殴,以及Client自己身份的憑證涮帘。

(4) AS驗證通過后,向Client返回“訪問令牌”笑诅。訪問令牌也有多種類型调缨,若為bearer類型疮鲫,那么誰持有訪問令牌,誰就能訪問資源弦叶。

(5) Client攜帶“訪問令牌”訪問RS上的資源俊犯。在令牌的有效期內(nèi),Client可以多次攜帶令牌去訪問資源伤哺。

(6) RS驗證令牌的有效性燕侠,比如是否偽造、是否越權(quán)立莉、是否過期绢彤,驗證通過后,才能提供服務(wù)蜓耻。

2.4 授權(quán)碼類型的開放授權(quán)

如圖2所示茫舶,授權(quán)碼類型的開放授權(quán)協(xié)議流程描述如下:


(1) Client初始化協(xié)議的執(zhí)行流程。首先通過HTTP 302來重定向RO用戶代理到AS媒熊。Client在redirect_uri中應(yīng)包含如下參數(shù):client_id, scope (描述被訪問的資源), redirect_uri (即Client的URI), state (用于抵制CSRF攻擊). 此外奇适,請求中還可以包含access_type和approval_prompt參數(shù)坟比。當(dāng)approval_prompt=force時芦鳍,AS將提供交互頁面,要求RO必須顯式地批準(zhǔn)(或拒絕)Client的此次請求葛账。如果沒有approval_prompt參數(shù)柠衅,則默認為RO批準(zhǔn)此次請求。當(dāng)access_type=offline時籍琳,AS將在頒發(fā)access_token時菲宴,同時還會頒發(fā)一個refresh_token。因為access_token的有效期較短(如3600秒)趋急,為了優(yōu)化協(xié)議執(zhí)行流程喝峦,offline方式將允許Client直接持refresh_token來換取一個新的access_token。

(2) AS認證RO身份呜达,并提供頁面供RO決定是否批準(zhǔn)或拒絕Client的此次請求(當(dāng)approval_prompt=force時)谣蠢。

(3) 若請求被批準(zhǔn),AS使用步驟(1)中Client提供的redirect_uri重定向RO用戶代理到Client查近。redirect_uri須包含authorization_code眉踱,以及步驟1中Client提供的state。若請求被拒絕霜威,AS將通過redirect_uri返回相應(yīng)的錯誤信息谈喳。

(4) Client拿authorization_code去訪問AS以交換所需的access_token。Client請求信息中應(yīng)包含用于認證Client身份所需的認證數(shù)據(jù)戈泼,以及上一步請求authorization_code時所用的redirect_uri婿禽。

(5) AS在收到authorization_code時需要驗證Client的身份赏僧,并驗證收到的redirect_uri與第3步請求authorization_code時所使用的redirect_uri相匹配。如果驗證通過扭倾,AS將返回access_token次哈,以及refresh_token(若access_type=offline)。

如果讀者對這個流程的細節(jié)不甚清楚吆录,那么可以先看第3節(jié)的一個實例化描述窑滞,然后再回來看這部分內(nèi)容。

3. OAuth協(xié)議實例化描述

下面我以實例化方式來幫助讀者理解授權(quán)碼類型的授權(quán)協(xié)議的運行過程恢筝。假設(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)。

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



協(xié)議所涉及到的細節(jié)都已經(jīng)在圖3上了移剪,所以不打算再做詳細介紹了。若看懂了此圖薪者,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) 通過消息認證碼來認證Client身份蓬坡,典型的算法有HMAC-SHA1。在這種方式下烟逊,Client無需傳送client_secret渣窜,只需發(fā)送消息請求的signature即可。由于不需要向AS傳遞敏感數(shù)據(jù)宪躯,所以它只需要使用http即可乔宿。

此外,在步驟(2)中访雪,Google授權(quán)服務(wù)器需要認證Alice的RO身份详瑞,并提供授權(quán)界面給Alice進行授權(quán)審批掂林。今天Google提供的實例如圖4、圖5所示坝橡,僅供讀者理解OAuth這種“現(xiàn)場授權(quán)”或"在線授權(quán)"的含義泻帮。



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

4.1 為何引入authorization_code?

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

HTTP/1.1 302

Location:

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被傳遞給其它惡意站點,也可能存在于瀏覽器cacher或log文件中招刨,這就給攻擊者盜取access_token帶來了很多機會霎俩。另外,此協(xié)議也不應(yīng)該假設(shè)RO用戶代理的行為是可信賴的沉眶,因為RO的瀏覽器可能早已被攻擊者植入了跨站腳本用來監(jiān)聽access_token。因此杉适,access_token通過RO的用戶代理傳遞給Client谎倔,會顯著擴大access_token被泄露的風(fēng)險。 但authorization_code可以通過redirect_uri方式來傳遞猿推,是因為authorization_code并不像access_token一樣敏感片习。即使authorization_code被泄露,攻擊者也無法直接拿到access_token蹬叭,因為拿authorization_code去交換access_token是需要驗證Client的真實身份藕咏。也就是說,除了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ù)需要保護access_token不被泄露。

(2) 引入authorization_code還會帶來如下的好處梦碗。由于協(xié)議需要驗證Client的身份禽绪,如果不引入authorization_code,這個Client的身份認證只能通過第1步的redirect_uri來傳遞洪规。同樣由于redirect_uri是一個不安全信道丐一,這就額外要求Client必須使用數(shù)字簽名技術(shù)來進行身份認證,而不能用簡單的密碼或口令認證方式淹冰。引入authorization_code之后库车,AS可以直接對Client進行身份認證(見步驟4和5),而且可以支持任意的Client認證方式(比如樱拴,簡單地直接將Client端密鑰發(fā)送給AS)柠衍。

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

4.2 基于Web安全的考慮

OAuth協(xié)議設(shè)計不同于簡單的網(wǎng)絡(luò)安全協(xié)議的設(shè)計裆泳,因為OAuth需要考慮各種Web攻擊叹洲,比如CSRF (Cross-Site Request Forgery), XSS (Cross Site Script), Clickjacking。要理解這些攻擊原理工禾,讀者需要對瀏覽器安全(eg, Same Origin Policy, 同源策略)有基本理解运提。比如,在redirect_uri中引入state參數(shù)就是從瀏覽器安全角度考慮的闻葵,有了它就可以抵制CSRF攻擊民泵。如果沒有這個參數(shù),攻擊者便可以在redirect_uri中注入攻擊者提供的authorization_code或access_token槽畔,結(jié)果可能導(dǎo)致Client訪問錯誤的資源(比如栈妆,將款項匯到一個錯誤的帳號)。

基于Web安全的考慮,OAuth協(xié)議文檔中已經(jīng)有了比較全面的闡述签钩,所以我不打算在此文中進行展開掏呼,有興趣的讀者請參考[1]。

5. 結(jié)語

本文對OAuth 2.0 開放授權(quán)協(xié)議及其設(shè)計上的安全性考慮做了一個基本的介紹铅檩,希望能給參與安全協(xié)議設(shè)計和開發(fā)的同學(xué)起到一點幫助憎夷。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市昧旨,隨后出現(xiàn)的幾起案子拾给,更是在濱河造成了極大的恐慌,老刑警劉巖兔沃,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蒋得,死亡現(xiàn)場離奇詭異,居然都是意外死亡乒疏,警方通過查閱死者的電腦和手機额衙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來怕吴,“玉大人窍侧,你說我怎么就攤上這事∽粒” “怎么了伟件?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長议经。 經(jīng)常有香客問我斧账,道長,這世上最難降的妖魔是什么煞肾? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任咧织,我火速辦了婚禮,結(jié)果婚禮上扯旷,老公的妹妹穿的比我還像新娘拯爽。我一直安慰自己,他們只是感情好钧忽,可當(dāng)我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著逼肯,像睡著了一般耸黑。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上篮幢,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天大刊,我揣著相機與錄音,去河邊找鬼三椿。 笑死缺菌,一個胖子當(dāng)著我的面吹牛葫辐,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播伴郁,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼耿战,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了焊傅?” 一聲冷哼從身側(cè)響起剂陡,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎狐胎,沒想到半個月后鸭栖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡握巢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年晕鹊,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片暴浦。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡溅话,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出肉渴,到底是詐尸還是另有隱情公荧,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布同规,位于F島的核電站循狰,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏券勺。R本人自食惡果不足惜绪钥,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望关炼。 院中可真熱鬧程腹,春花似錦、人聲如沸儒拂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽社痛。三九已至见转,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蒜哀,已是汗流浹背斩箫。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人乘客。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓狐血,卻偏偏與公主長得像,于是被迫代替她去往敵國和親易核。 傳聞我的和親對象是個殘疾皇子匈织,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容