OIDC & OAuth2.0 協(xié)議及其授權(quán)模式詳解|認(rèn)證協(xié)議最佳實(shí)踐系列【1】


OIDC / OAuth2.0 是一種開放的標(biāo)準(zhǔn),可以幫助應(yīng)用程序安全地訪問用戶的資源,而無需將用戶的憑據(jù)(如用戶名和密碼)暴露給應(yīng)用程序,我們可以通過標(biāo)準(zhǔn)協(xié)議,建立集中的用戶目錄和統(tǒng)一認(rèn)證中心,將內(nèi)外部業(yè)務(wù)系統(tǒng)的登錄認(rèn)證統(tǒng)一到認(rèn)證中心,實(shí)現(xiàn)集中化的管理,從而避免每套業(yè)務(wù)系統(tǒng)都要搭建一套用戶體系所造成的管理側(cè)不便及安全側(cè)的風(fēng)險(xiǎn)。
本文將帶各位詳細(xì)了解 OAuth 2.0 & OIDC 及其授權(quán)模式。
01.協(xié)議介紹
1.1?OAuth 2.0 & OIDC
OAuth 2.0 是一個(gè)授權(quán)框架,使應(yīng)用程序能夠獲得對(duì) HTTP 服務(wù)上用戶帳戶的有限訪問權(quán)限,例如 Facebook、GitHub 和 DigitalOcean。它通過將用戶認(rèn)證委托給托管用戶帳戶的服務(wù),并授權(quán)第三方應(yīng)用程序訪問用戶帳戶來實(shí)現(xiàn)。
OpenID Connect (OIDC) 是建立在 OAuth 2.0 框架之上的簡單身份層。它在 OAuth 2.0 提供的授權(quán)的基礎(chǔ)上添加了認(rèn)證。
初看上面這段話你可能很難理解,這里用白話解釋下,OAuth 2.0 在設(shè)計(jì)之初,是為了 API 安全的問題,它是一個(gè)授權(quán)協(xié)議,而 OIDC 則在 OAuth2.0 協(xié)議的基礎(chǔ)上,提供了用戶認(rèn)證、獲取用戶信息等的標(biāo)準(zhǔn)實(shí)現(xiàn),當(dāng)然我們也可以理解獲取用戶信息也是一個(gè) API ,用 OAuth 2.0 也沒問題的,考慮到讀者的感受,在這里不要過于糾結(jié),只要記住?OIDC 是完全兼容 OAuth2.0 的,我們現(xiàn)在也推薦用 OIDC。
1.2 術(shù)語介紹

啥啥啥,寫的這都是啥,小白看到這些腦袋都大了,我在這里重點(diǎn)說下 OIDC/OAuth2.0 協(xié)議交互時(shí)所參與的幾個(gè)角色,等你對(duì)協(xié)議熟悉了,可以反過頭來再看下相關(guān)的介紹,在接下來的授權(quán)模式介紹中,我們會(huì)結(jié)合這四個(gè)角色,介紹下不同授權(quán)模式的流程。
資源持有者(End User / Resource Owner) 終端用戶
應(yīng)用/客戶端(Client)應(yīng)用的前端,可以是 web 端、App 端、移動(dòng)端應(yīng)用
資源服務(wù)器(Resource Server) Client 對(duì)應(yīng)的后臺(tái)
認(rèn)證服務(wù)器(OpenID Provider / Authorization Server)即 Authing
1.3?Client 類型介紹
OAuth2.0 / OIDC 中定義了 2 種 Client 類型:
我們?cè)谶@里解釋下:
Confidential Clients 機(jī)密型應(yīng)用:能夠安全的存儲(chǔ)憑證(client_secret),例如有后端服務(wù),你的前端是 Vue,后臺(tái)是 Java ,那么可以理解為機(jī)密性應(yīng)用,因?yàn)槟愕暮蠖四軌虬踩谋4?client_secret,而不會(huì)將 client_secret 直接暴露給用戶,此時(shí)你可以使用授權(quán)碼模式。
Public Clients 公共型應(yīng)用:無法安全存儲(chǔ)憑證(Client Secrets),例如 SPA 、移動(dòng)端、或者完全前后端分離的應(yīng)用,應(yīng)當(dāng)使用授權(quán)碼 + PKCE 模式
1.4?OIDC 授權(quán)模式與選型建議
重點(diǎn)來啦!我們要了解授權(quán)模式,才能更好的針對(duì)系統(tǒng)類型進(jìn)行授權(quán)模式的選型,避免由于授權(quán)模式選型不當(dāng)所造成的開發(fā)工作增加和安全側(cè)的漏洞。
授權(quán)模式

選型建議

02.授權(quán)模式詳細(xì)介紹
2.1?授權(quán)碼模式(Authorization Code)
授權(quán)碼模式適合應(yīng)用具備后端服務(wù)器的場景。授權(quán)碼模式要求應(yīng)用必須能夠安全存儲(chǔ)密鑰,用于后續(xù)使用授權(quán)碼換 Access Token。授權(quán)碼模式需要通過瀏覽器與終端用戶交互完成認(rèn)證授權(quán),然后通過瀏覽器重定向?qū)⑹跈?quán)碼發(fā)送到后端服務(wù),之后進(jìn)行授權(quán)碼換 Token 以及 Token 換用戶信息。
整體上,有以下流程:
1. 在你的應(yīng)用中,讓用戶訪問登錄鏈接,瀏覽器跳轉(zhuǎn)到 Authing,用戶在 Authing 完成認(rèn)證。
2. 瀏覽器接收到一個(gè)從 Authing 服務(wù)器發(fā)來的授權(quán)碼。
3. 瀏覽器通過重定向?qū)⑹跈?quán)碼發(fā)送到你的應(yīng)用后端。
4. 你的應(yīng)用服務(wù)將授權(quán)碼發(fā)送到 Authing 獲取 AccessToken 和 IdToken,如果需要,還會(huì)返回 refresh token。
5. 你的應(yīng)用后端現(xiàn)在知道了用戶的身份,后續(xù)可以保存用戶信息,重定向到前端其他頁面,使用 AccessToken 調(diào)用資源方的其他 API 等等。
流程圖如下:

2.2?授權(quán)碼 + PKCE 模式(Authorization Code With PKCE)
如果你的應(yīng)用是一個(gè) SPA 前端應(yīng)用或移動(dòng)端 App,建議使用授權(quán)碼 + PKCE 模式來完成用戶的認(rèn)證和授權(quán)。授權(quán)碼 + PKCE 模式適合不能安全存儲(chǔ)密鑰的場景(例如前端瀏覽器) 。
我們解釋下 code_verifier 和 code_challenge。
code_verifier:在 [A-Z] / [a-z] / [0-9] / "-" / "." / "_" / "~" 范圍內(nèi),生成43-128位的隨機(jī)字符串。
code_challenge:則是對(duì) code_verifier 通過 code_challenge_method 例如 sha256 轉(zhuǎn)換得來的。
用大白話講下就是在認(rèn)證是用戶攜帶的是加密后的 code_challenge ,在用戶認(rèn)證成功獲取 Token 時(shí),客戶端證明自己的方式則是把 code_verifier 原文發(fā)送,認(rèn)證中心收到獲取 Token 請(qǐng)求時(shí)通過 code_verifier ?+ code_challenge_method 進(jìn)行轉(zhuǎn)換,發(fā)現(xiàn)最終結(jié)果與 code_challenge 匹配則返回 Token ,否則拒絕。
整體上,有以下流程:
1.?在你的應(yīng)用中,讓用戶訪問登錄鏈接(包含 code_challenge ) ,瀏覽器跳轉(zhuǎn)到 Authing,用戶在 Authing 完成認(rèn)證。
2.?瀏覽器接收到一個(gè)從 Authing 服務(wù)器發(fā)來的授權(quán)碼。
3.?瀏覽器通過重定向?qū)⑹跈?quán)碼發(fā)送到你的應(yīng)用前端。
4.?你的應(yīng)用將授權(quán)碼和 code_verifier 發(fā)送到 Authing 獲取 AccessToken 和 IdToken,如果需要,還會(huì)返回 Refresh token。
5.?你的應(yīng)用前端現(xiàn)在知道了用戶的身份,后續(xù)使用 Access token 換取用戶信息,重定向到前端其他頁面,使用 AccessToken 調(diào)用資源方的其他 API 等等。
流程圖如下:
2.3?客戶端憑證模式(Client Credentials)
Client Credentials 模式用于進(jìn)行服務(wù)器對(duì)服務(wù)器間的授權(quán)(M2M 授權(quán)),期間沒有用戶的參與。你需要?jiǎng)?chuàng)建編程訪問賬號(hào),并將 AK、SK 密鑰對(duì)交給你的資源調(diào)用方。
注意??:Client Credentials 模式不支持 Refresh Token。
整體上,有以下流程:
1. 資源調(diào)用方將他的憑證 AK、SK 以及需要請(qǐng)求的權(quán)限 scope 發(fā)送到 Authing 授權(quán)端點(diǎn)。
2. 如果憑證正確,并且調(diào)用方具備資源權(quán)限,Authing 為其頒發(fā) AccessToken。
流程圖如下:

2.4?隱式模式(Implicit)(不推薦)
隱式模式適合不能安全存儲(chǔ)密鑰的場景(例如前端瀏覽器),不推薦此模式,建議采用其他模式。在隱式模式中,應(yīng)用不需要使用 code 換 token,無需請(qǐng)求?/token?端點(diǎn),AccessToken 和 IdToken 會(huì)直接從認(rèn)證端點(diǎn)返回。
注意??:因?yàn)殡[式模式用于不能安全存儲(chǔ)密鑰的場景,所以隱式模式不支持獲取 Refresh Token。
整體上,有以下流程:
1.?在你的應(yīng)用中,讓用戶訪問登錄鏈接,瀏覽器跳轉(zhuǎn)到 Authing,用戶在 Authing 完成認(rèn)證。
2.?Authing 將瀏覽器重定向到你的應(yīng)用回調(diào)地址,AccessToken 和 IdToken 作為 URL hash 傳遞。
3.?你的應(yīng)用從 URL 中取出 token。
4.?你的應(yīng)用可以將 AccessToken 與 IdToken 保存,以便后續(xù)使用,例如攜帶 AccessToken 訪問資源服務(wù)器,攜帶 IdToken 請(qǐng)求服務(wù)端從而服務(wù)端能夠辨別用戶身份。
流程圖如下:

2.5?密碼模式(Password)(不推薦)
不推薦使用此模式,盡量使用其他模式。只有其他模式都無法解決問題時(shí)才會(huì)考慮使用密碼模式。如果使用密碼模式,請(qǐng)確保你的應(yīng)用代碼邏輯非常安全,不會(huì)被黑客攻擊,否則將會(huì)直接泄露用戶的賬密。一般用于改造集成非常古老的應(yīng)用,否則絕對(duì)不要把它作為你的第一選擇。
整體上,有以下流程:
1. 你的應(yīng)用讓用戶輸入賬密信息。
2. 你的應(yīng)用將用戶賬密發(fā)送到 Authing 。
3. 如果賬密正確,Authing 返回 token 。
流程圖如下:

2.6?設(shè)備代碼模式(Device Code)(幾乎用不到)
對(duì)于一些連接到互聯(lián)網(wǎng)的輸入受限設(shè)備,設(shè)備不會(huì)直接驗(yàn)證用戶身份,而是讓用戶通過鏈接或二維碼轉(zhuǎn)到手機(jī)或電腦上進(jìn)行認(rèn)證,從而避免了用戶無法輕松輸入文本所帶來的糟糕體驗(yàn)。
Device Code Flow?與前面幾個(gè)不太一樣,開始不再是由資源持有者發(fā)起,而是由客戶端開始。甚至登錄的方法與客戶端還沒有特別的關(guān)聯(lián)。
大致流程說明如下:
1. 客戶端發(fā)起向認(rèn)證服務(wù)器取得 device_code 和user_code 。
2. 客戶端通過二維碼或者其他方式將 user_code交給資源持有者。
3. 資源持有者透過某個(gè)端點(diǎn) (endpoint) 與user_code 進(jìn)行認(rèn)證。
4. 客戶端通過 device_code 輪訓(xùn)認(rèn)證服務(wù)器是否有人認(rèn)證,若有人認(rèn)證則會(huì)返回 access_token 。
流程圖如下:

一個(gè)設(shè)計(jì)良好的系統(tǒng),都需要一個(gè)標(biāo)準(zhǔn)、安全、可擴(kuò)展的用戶認(rèn)證協(xié)議,無論是 ToC 還是 ToE ,接來下我們還會(huì)針對(duì)具體的授權(quán)模式結(jié)合實(shí)際場景講一下具體的模式。
03.本章總結(jié)
1.?本章我們介紹了 OIDC 和 OAuth2.0 兩個(gè)協(xié)議,在使用起來,這兩個(gè)協(xié)議并沒有太大的區(qū)別,OAuth2.0 是一個(gè)授權(quán)協(xié)議,OIDC 協(xié)議則是在 OAuth2.0 的提供的授權(quán)的基礎(chǔ)上添加了認(rèn)證。
2.?授權(quán)模式,我們分別介紹了授權(quán)碼模式(Authorization Code) 、授權(quán)碼 + PKCE 模式(Authorization Code With PKCE) 、客戶端憑證模式(Client Credentials) 、隱式模式(Implicit)(不推薦)、密碼模式(Password) (不推薦)、設(shè)備代碼模式(Device Code)(幾乎用不到) 。
3.?授權(quán)模式選擇
如果我們的應(yīng)用是 WEB 端應(yīng)用,那我們應(yīng)該選擇授權(quán)碼模式(Authorization Code)
如果我們是原生應(yīng)用,例如 SPA ,移動(dòng)端,那我們應(yīng)該選擇授權(quán)碼 + PKCE 模式(Authorization Code With PKCE)
如果我們是想把應(yīng)用的 API 給第三方服務(wù)安全的調(diào)用,則需要選擇客戶端憑證模式(Client Credentials)
接下來我們還會(huì)詳細(xì)介紹授權(quán)碼模式(Authorization Code)、授權(quán)碼 + PKCE 模式(Authorization Code With PKCE)、客戶端憑證模式(Client Credentials)如何接入 Authing。敬請(qǐng)期待!