基于OAuth2的OIDC (OpenId Connect) 身份認(rèn)證

OIDC協(xié)議

OIDC(OpenID Connect)是在OAuth2上構(gòu)建了一個(gè)身份層示弓,是一個(gè)基于OAuth2協(xié)議的身份認(rèn)證標(biāo)準(zhǔn)協(xié)議打毛。

OAuth2協(xié)議

OAuth2是一個(gè)授權(quán)協(xié)議,它無法提供完善的身份認(rèn)證功能【1】导坟,OIDC使用OAuth2的授權(quán)服務(wù)器來為第三方客戶端提供用戶的身份認(rèn)證魔种,并把對應(yīng)的身份認(rèn)證信息傳遞給客戶端擎勘。

使用OAuth2進(jìn)行認(rèn)證的常見誤區(qū)

如果用OAuth2進(jìn)行認(rèn)證,會有許多問題刀崖。

  • 在OAuth2中惊科,token被設(shè)計(jì)成是對客戶端不透明的,但在用戶身份認(rèn)證的上下文環(huán)境中, 客戶端往往需要能夠從token中派生一些信息蒲跨。這可以通過定義一個(gè)雙重目的(dual-purposing)的客戶端以解析和理解的token來完成译断。但是OAuth2協(xié)議并沒有為access token本身定義特定的格式貨結(jié)構(gòu),因此需要在OAuth2協(xié)議的基礎(chǔ)上或悲,利用諸如OpenId Connect的ID Token在響應(yīng)中提供一個(gè)次要的標(biāo)記孙咪,它將和access token一起發(fā)送給客戶端中。一方面巡语,保持了token是對客戶端的不透明翎蹈,另一方面,為客戶端提供了其所需的認(rèn)證信息男公。
  • OAuth保護(hù)的是資源荤堪,獲取用戶屬性的API(identity API)通常沒有辦法告訴你用戶是否存在。而且枢赔,在某些情況下澄阳,用戶無需身份驗(yàn)證即可獲得access token(比如[認(rèn)證授權(quán)] 1.OAuth2授權(quán) - 5.4 Client Credentials Grant)。也就是說Access Token并不能和某個(gè)用戶關(guān)聯(lián)起來踏拜。
  • 在某些場合碎赢,例如,使用implicit流程(這個(gè)流程中直接把a(bǔ)cces token作為url的hash參數(shù)([認(rèn)證授權(quán)] 1.OAuth2 授權(quán) - 5.2.2 Access Token Response))中速梗,User Agent可以獲得token肮塞,也就你開辟了一個(gè)注入 access token到應(yīng)用程序外部(并可能在應(yīng)用程序外部泄露)的地方襟齿。如果Client不通過某種機(jī)制驗(yàn)證access token,則它無法區(qū)分access token是有效的令牌還是攻擊的令牌枕赵。
  • 很可能有一個(gè)幼稚的(naive)客戶端猜欺,從其他的客戶端拿到一個(gè)有效的token來作為自己的登錄事件。畢竟token是有效的拷窜,對API的訪問也會返回有效的用戶信息开皿。問題在于沒有用戶做任何事情來證明用戶存在,在這種情況下装黑,用戶甚至都沒有授權(quán)給幼稚的(naive)客戶端副瀑。
  • 如果攻擊者能夠攔截或者替換來自Client的一個(gè)調(diào)用,它可能會改變返回的用戶信息恋谭,而客戶端卻無法感知這一情況糠睡。這將允許攻擊者通過簡單地在正確的調(diào)用序列中交換用戶標(biāo)識符來模擬一個(gè)幼稚的(naive)Client上的用戶。
  • 基于OAuth 身份(identity)API的最大問題在于疚颊,即使使用完全符合OAuth的機(jī)制狈孔,不同的提供程序不可避免的會使用不同的方式實(shí)現(xiàn)身份(identity)API。

OIDC核心概念:ID Token

OAuth2提供了Access Token來解決授權(quán)第三方客戶端訪問受保護(hù)資源的問題材义;OIDC在這個(gè)基礎(chǔ)上提供了ID Token來解決第三方客戶端標(biāo)識用戶身份認(rèn)證的問題均抽。OIDC的核心在于在OAuth2的授權(quán)流程中,一并提供用戶的身份認(rèn)證信息(ID Token)給到第三方客戶端其掂,ID Token使用JWT格式來包裝油挥。此外還提供了UserInfo的接口,用戶獲取用戶的更完整的信息款熬。

參與角色

主要的術(shù)語以及概念介紹:

  • EU:End User:一個(gè)人類用戶深寥。
  • RP:Relying Party ,用來代指OAuth2中的受信任的客戶端,身份認(rèn)證和授權(quán)信息的消費(fèi)方贤牛;
  • OP:OpenID Provider惋鹅,有能力提供EU認(rèn)證的服務(wù)(比如OAuth2中的授權(quán)服務(wù)),用來為RP提供EU的身份認(rèn)證信息殉簸;
  • ID Token:JWT格式的數(shù)據(jù)闰集,包含EU身份認(rèn)證的信息。
  • UserInfo Endpoint:用戶信息接口(受OAuth2保護(hù))般卑,當(dāng)RP使用Access Token訪問時(shí)武鲁,返回授權(quán)用戶的信息,此接口必須使用HTTPS蝠检。

工作流程

OIDC的流程由以下5個(gè)步驟構(gòu)成:

  1. RP發(fā)送一個(gè)認(rèn)證請求給OP洞坑;
  2. OPEU進(jìn)行身份認(rèn)證,然后提供授權(quán)蝇率;
  3. OPID TokenAccess Token(需要的話)返回給RP迟杂;
  4. RP使用Access Token發(fā)送一個(gè)請求UserInfo EndPoint
  5. UserInfo EndPoint返回EUClaims本慕。
    oidc.jpg

    注意這里面RP發(fā)往OP的請求排拷,是屬于Authentication類型的請求,雖然在OIDC中是復(fù)用OAuth2的Authorization請求通道锅尘,但是用途是不一樣的监氢,且OIDC的AuthN請求中scope參數(shù)必須要有一個(gè)值為的openid的參數(shù),用來區(qū)分這是一個(gè)OIDC的Authentication請求藤违,而不是OAuth2的Authorization請求浪腐。

什么是ID Token

OIDC對OAuth2最主要的擴(kuò)展就是提供了ID TokenID Token是一個(gè)安全令牌顿乒,是一個(gè)授權(quán)服務(wù)器提供的包含用戶信息(由一組Cliams構(gòu)成以及其他輔助的Cliams)的JWT格式的數(shù)據(jù)結(jié)構(gòu)议街。
另外ID Token必須使用JWS進(jìn)行簽名和JWE加密,從而提供認(rèn)證的完整性璧榄、不可否認(rèn)性以及可選的保密性特漩。一個(gè)ID Token的例子如下:

 1 {
 2    "iss": "https://server.example.com",
 3    "sub": "24400320",
 4    "aud": "s6BhdRkqt3",
 5    "nonce": "n-0S6_WzA2Mj",
 6    "exp": 1311281970,
 7    "iat": 1311280970,
 8    "auth_time": 1311280969,
 9    "acr": "urn:mace:incommon:iap:silver"
10   }

如何獲取ID Token

因?yàn)镺IDC基于OAuth2,所以O(shè)IDC的認(rèn)證流程主要是由OAuth2的幾種授權(quán)流程延伸而來的骨杂,有以下3種:

  1. Authorization Code Flow:使用OAuth2的授權(quán)碼來換取Id TokenAccess Token涂身。
  2. Implicit Flow:使用OAuth2的Implicit流程獲取Id TokenAccess Token
  3. Hybrid Flow:混合Authorization Code Flow+Implici Flow搓蚪。

Resource Owner Password Credentials Grant是需要用途提供賬號密碼給RP的蛤售,賬號密碼給到RP了,就不再需要ID Token了妒潭。

Client Credentials Grant這種方式根本就不需要用戶參與悴能,更談不上用戶身份認(rèn)證了。這也能反映授權(quán)和認(rèn)證的差異杜耙,以及只使用OAuth2來做身份認(rèn)證的事情是遠(yuǎn)遠(yuǎn)不夠的搜骡,也是不合適的。

這里主要介紹基于Authorization Code的認(rèn)證請求/答復(fù)佑女。

基于Authorization Code的認(rèn)證請求的請求

所有的Token都是通過Token EndPoint來發(fā)放的记靡。構(gòu)建一個(gè)OIDC的Authentication Request需要提供如下的參數(shù):

  • scope:必須。OIDC的請求必須包含值為openid的scope的參數(shù)团驱。
  • response_type:必選摸吠。同OAuth2。
  • client_id:必選嚎花。同OAuth2寸痢。
  • redirect_uri:必選。同OAuth2紊选。
  • state:推薦啼止。同OAuth2道逗。防止CSRF, XSRF。

以上這5個(gè)參數(shù)是和OAuth2相同的献烦。除此之外滓窍,還定義了一些參數(shù)【2】例如:

  • response_mode:可選。OIDC新定義的參數(shù)巩那,用來指定Authorization Endpoint以何種方式返回?cái)?shù)據(jù)吏夯。

一個(gè)簡單的示例如下:

GET /authorize?
    response_type=code
    &scope=openid%20profile%20email
    &client_id=s6BhdRkqt3
    &state=af0ifjsldkj
    &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb HTTP/1.1
  Host: server.example.com
基于Authorization Code的認(rèn)證請求的響應(yīng)

授權(quán)服務(wù)器接收到認(rèn)證請求之后,需要對請求參數(shù)做嚴(yán)格的驗(yàn)證即横。驗(yàn)證通過后引導(dǎo)EU進(jìn)行身份認(rèn)證并且同意授權(quán)噪生。在這一切都完成后,會重定向到RP指定的回調(diào)地址东囚,并且把codestate參數(shù)傳遞過去跺嗽。比如:

  HTTP/1.1 302 Found
  Location: https://client.example.org/cb?
    code=SplxlOBeZQQYbYS6WxSbIA
    &state=af0ifjsldkj
獲取ID Token

RP使用上一步獲得的code來請求Token EndPoint,這一步同OAuth2舔庶。然后Token EndPoint會返回響應(yīng)的Token抛蚁,其中除了OAuth2規(guī)定的部分?jǐn)?shù)據(jù)外,還會附加一個(gè)id_token的字段惕橙。id_token字段就是上面提到的ID Token瞧甩。例如:

  HTTP/1.1 200 OK
  Content-Type: application/json
  Cache-Control: no-store
  Pragma: no-cache

  {
   "access_token": "SlAV32hkKG",
   "token_type": "Bearer",
   "refresh_token": "8xLOxBtZp8",
   "expires_in": 3600,
   "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjFlOWdkazcifQ.ewogImlzc
     yI6ICJodHRwOi8vc2VydmVyLmV4YW1wbGUuY29tIiwKICJzdWIiOiAiMjQ4Mjg5
     NzYxMDAxIiwKICJhdWQiOiAiczZCaGRSa3F0MyIsCiAibm9uY2UiOiAibi0wUzZ
     fV3pBMk1qIiwKICJleHAiOiAxMzExMjgxOTcwLAogImlhdCI6IDEzMTEyODA5Nz
     AKfQ.ggW8hZ1EuVLuxNuuIJKX_V8a_OMXzR0EHR9R6jgdqrOOF4daGU96Sr_P6q
     Jp6IcmD3HP99Obi1PRs-cwh3LO-p146waJ8IhehcwL7F09JdijmBqkvPeB2T9CJ
     NqeGpe-gccMg4vfKjkM8FcGvnzZUN4_KSP0aAp1tOJ1zZwgjxqGByKHiOtX7Tpd
     QyHE5lcMiKPXfEIQILVq0pc_E2DzL7emopWoaoZTF_m0_N0YzFC6g6EJbOEoRoS
     K5hoDalrcvRYLSrQAZZKflyuVCyixEoV9GfNQC3_osjzw2PAithfubEEBLuVVk4
     XUVrWOLrLl0nx7RkKU8NXNHq-rvKMzqg"
  }

其中看起來一堆亂碼的部分就是JWT格式的ID Token。在RP拿到這些信息之后弥鹦,需要對id_token以及access_token進(jìn)行驗(yàn)證肚逸。至此,可以說用戶身份認(rèn)證就可以完成了彬坏,后續(xù)可以根據(jù)UserInfo EndPoint獲取更完整的信息朦促。

OIDC協(xié)議簇

除了Core核心規(guī)范內(nèi)容多一點(diǎn)之外,另外7個(gè)都是很簡單且簡短的規(guī)范栓始,另外Core是基于OAuth2的务冕,也就是說其中很多東西在復(fù)用OAuth2。


oicd_p_s.png

OpenId Connect定義了一個(gè)發(fā)現(xiàn)協(xié)議幻赚,它允許Client輕松的獲取有關(guān)如何和特定的身份認(rèn)證提供者進(jìn)行交互的信息禀忆。在另一方面,還定義了一個(gè)Client注冊協(xié)議落恼,允許Client引入新的身份提供程序(identity providers)箩退。通過這兩種機(jī)制和一個(gè)通用的身份API,OpenId Connect可以運(yùn)行在互聯(lián)網(wǎng)規(guī)模上運(yùn)行良好佳谦,在那里沒有任何一方事先知道對方的存在戴涝。

UserInfo Endpoint

UserIndo EndPoint是一個(gè)受OAuth2保護(hù)的資源。在RP得到Access Token后可以請求此資源,然后獲得一組EU相關(guān)的Claims啥刻,這些信息可以說是ID Token的擴(kuò)展奸鸯,

  GET /userinfo HTTP/1.1
  Host: server.example.com
  Authorization: Bearer SlAV32hkKG

成功之后相應(yīng)如下:

  HTTP/1.1 200 OK
  Content-Type: application/json

  {
   "sub": "248289761001",
   "name": "Jane Doe",
   "given_name": "Jane",
   "family_name": "Doe",
   "preferred_username": "j.doe",
   "email": "janedoe@example.com",
   "picture": "http://example.com/janedoe/me.jpg"
  }

【1】OAuth2中的access_token
【2】[認(rèn)證 & 授權(quán)] 4. OIDC(OpenId Connect)身份認(rèn)證(核心部分)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市郑什,隨后出現(xiàn)的幾起案子府喳,更是在濱河造成了極大的恐慌,老刑警劉巖蘑拯,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異兜粘,居然都是意外死亡申窘,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門孔轴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來剃法,“玉大人,你說我怎么就攤上這事路鹰〈蓿” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵晋柱,是天一觀的道長优构。 經(jīng)常有香客問我,道長雁竞,這世上最難降的妖魔是什么钦椭? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮碑诉,結(jié)果婚禮上彪腔,老公的妹妹穿的比我還像新娘。我一直安慰自己进栽,他們只是感情好德挣,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著快毛,像睡著了一般格嗅。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上祸泪,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天吗浩,我揣著相機(jī)與錄音,去河邊找鬼没隘。 笑死懂扼,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播阀湿,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼赶熟,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了陷嘴?” 一聲冷哼從身側(cè)響起映砖,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎灾挨,沒想到半個(gè)月后邑退,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡劳澄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年地技,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片秒拔。...
    茶點(diǎn)故事閱讀 38,161評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡莫矗,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出砂缩,到底是詐尸還是另有隱情作谚,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布庵芭,位于F島的核電站妹懒,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏喳挑。R本人自食惡果不足惜彬伦,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望伊诵。 院中可真熱鬧单绑,春花似錦、人聲如沸曹宴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽笛坦。三九已至区转,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間版扩,已是汗流浹背废离。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留礁芦,地道東北人蜻韭。 一個(gè)月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓悼尾,卻偏偏與公主長得像,于是被迫代替她去往敵國和親肖方。 傳聞我的和親對象是個(gè)殘疾皇子闺魏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評論 2 344

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