[認證 & 授權(quán)] 5. OIDC(OpenId Connect)身份認證(擴展部分)
在上一篇[認證授權(quán)] 4.OIDC(OpenId Connect)身份認證(核心部分)中解釋了OIDC的核心部分的功能,即OIDC如何提供id token來用于認證。由于OIDC是一個協(xié)議族,如果只是簡單的只關(guān)注其核心部分其實是不足以搭建一個完整的OIDC服務(wù)的。本篇則解釋下OIDC中比較常用的幾個相關(guān)擴展協(xié)議,可以說是搭建OIDC服務(wù)必備的幾個擴展協(xié)議(在上一篇中有提到這幾個協(xié)議規(guī)范):
- Discovery:可選。發(fā)現(xiàn)服務(wù),使客戶端可以動態(tài)的獲取OIDC服務(wù)相關(guān)的元數(shù)據(jù)描述信息(比如支持那些規(guī)范,接口地址是什么等等)。
- OAuth 2.0 Multiple Response Types :可選。針對OAuth2的擴展,提供幾個新的response_type。
- OAuth 2.0 Form Post Response Mode:可選。針對OAuth2的擴展,OAuth2回傳信息給客戶端是通過URL的querystring和fragment這兩種方式,這個擴展標準提供了一基于form表單的形式把數(shù)據(jù)post給客戶端的機制。
- 會話管理:Session Management :可選。Session管理,用于規(guī)范OIDC服務(wù)如何管理Session信息;Front-Channel Logout:可選。基于前端的注銷機制。
1 OIDC Discovery 規(guī)范
顧名思義,Discovery定義了一個服務(wù)發(fā)現(xiàn)的規(guī)范,它定義了一個api( /.well-known/openid-configuration ),這個api返回一個json數(shù)據(jù)結(jié)構(gòu),其中包含了一些OIDC中提供的服務(wù)以及其支持情況的描述信息,這樣可以使得oidc服務(wù)的RP可以不再硬編碼OIDC服務(wù)接口信息。這個api返回的示例信息如下(這里面只是一部分,更完整的信息在官方的規(guī)范中有詳細的描述和解釋說明:http://openid.net/specs/openid-connect-discovery-1_0.html):

相信大家都看得懂的,它包含有授權(quán)的url,獲取token的url,注銷token的url,以及其對OIDC的擴展功能支持的情況等等信息,這里就不再詳細解釋每一項了。
2 OAuth2 擴展:Multiple Response Types
在本系列的第一篇博客[認證授權(quán)] 1.OAuth2授權(quán)中解釋OAuth2的授權(quán)請求的時候,其請求參數(shù)中有一個 response_type 的參數(shù),其允許的值有 code 和 token 兩個,在這兩個的基礎(chǔ)上,OIDC增加了一個新值 id_token (詳細信息定義在http://openid.net/specs/oauth-v2-multiple-response-types-1_0.html):
- code:oauth2定義的。用于獲取authorization_code。
- token:oauth2定義的。用戶獲取access_token。
- id_token:OIDC定義的。用戶獲取id_token。
至此OIDC是支持三種類型的response_type的,不但如此,OIDC還允許了可以組合這三種類型,即在一個response_type中包含多個值(空格分隔)。比如當參數(shù)是這樣的時候 response_type=id_token token ,OIDC服務(wù)就會把access_token和id_token一并給到調(diào)用方。OIDC對這些類型的支持情況體現(xiàn)在上面提到的Discovery服務(wù)中返回的response_types_supported字段中:

3 OAuth2 擴展:Form Post Response Mode
在oauth2的授權(quán)碼流程中,當response_type設(shè)置為code的時候,oauth2的授權(quán)服務(wù)會把authorization_code通過url的query部分傳遞給調(diào)用方,比如這樣“https://client.lnh.dev/oauth2-callback?code=SplxlOBeZQQYbYS6WxSbIA&state=xyz”。
在oauth2的隱式授權(quán)流程中,當response_type設(shè)置為token的時候,oauth2的授權(quán)服務(wù)會直接把access_token通過url的fragment部分傳遞給調(diào)用方,比如這樣“http://client.lnh.dev/oauth2-callback#access_token=2YotnFZFEjr1zCsicMWpAA&state=xyz&expires_in=3600”;
在oauth2中,上面的兩種情況是其默認行為,并沒有通過參數(shù)來顯示的控制。OIDC在保持oauth2的默認行為的基礎(chǔ)上,增加了一個名為response_mode的參數(shù),并且增加了一種通過form表單傳遞信息的方式,即form_post(詳細信息定義在http://openid.net/specs/oauth-v2-form-post-response-mode-1_0.html)。OIDC服務(wù)對這個擴展的支持情況體現(xiàn)在上面提到的Discovery服務(wù)中返回的response_modes_supported字段中:

當reponse_mode設(shè)置為form_post的時候,OIDC則會返回如下的信息:
<html> <head><title>Submit This Form</title></head> <body onload="javascript:document.forms[0].submit()"> <form method="post" action="https://client.lnh.dev/oidc-callback"> <input type="hidden" name="state" value="DcP7csa3hMlvybERqcieLHrRzKBra"/> <input type="hidden" name="id_token" value="eyJhbGciOiJSUzI1NiIsImtpZCI6IjEifQ.eyJzdWIiOiJqb2huIiw iYXVkIjoiZmZzMiIsImp0aSI6ImhwQUI3RDBNbEo0c2YzVFR2cllxUkIiLC Jpc3MiOiJodHRwczpcL1wvbG9jYWxob3N0OjkwMzEiLCJpYXQiOjEzNjM5M DMxMTMsImV4cCI6MTM2MzkwMzcxMywibm9uY2UiOiIyVDFBZ2FlUlRHVE1B SnllRE1OOUlKYmdpVUciLCJhY3IiOiJ1cm46b2FzaXM6bmFtZXM6dGM6U0F NTDoyLjA6YWM6Y2xhc3NlczpQYXNzd29yZCIsImF1dGhfdGltZSI6MTM2Mz kwMDg5NH0.c9emvFayy-YJnO0kxUNQqeAoYu7sjlyulRSNrru1ySZs2qwqq wwq-Qk7LFd3iGYeUWrfjZkmyXeKKs_OtZ2tI2QQqJpcfrpAuiNuEHII-_fk IufbGNT_rfHUcY3tGGKxcvZO9uvgKgX9Vs1v04UaCOUfxRjSVlumE6fWGcq XVEKhtPadj1elk3r4zkoNt9vjUQt9NGdm1OvaZ2ONprCErBbXf1eJb4NW_h nrQ5IKXuNsQ1g9ccT5DMtZSwgDFwsHMDWMPFGax5Lw6ogjwJ4AQDrhzNCFc 0uVAwBBb772-86HpAkGWAKOK-wTC6ErRTcESRdNRe0iKb47XRXaoz5acA"/> </form> </body> </html>
這是一個會在html加載完畢后,通過一個自動提交的form表單,把id_token,access_token,authorization_code或者其他的相關(guān)數(shù)據(jù)POST到調(diào)用方指定的回調(diào)地址上。
4 OIDC 會話管理
綜合上篇提到的idtoken和前面的discovery服務(wù)以及針對oauth2的擴展,則可以讓OIDC服務(wù)的RP完成用戶認證的過程。那么如何主動的撤銷這個認證呢(也就是我們常說的退出登錄)?總結(jié)來說就是其認證的會話管理,OIDC單獨定義了3個獨立的規(guī)范來完成這件事情:
- Session Management :可選。Session管理,用于規(guī)范OIDC服務(wù)如何管理Session信息。
- Front-Channel Logout:可選。基于前端的注銷機制。
- Back-Channel Logout:可選。基于后端的注銷機制。
其中Session Management是OIDC服務(wù)自身管理會話的機制;Back-Channel Logout則是定義在純后端服務(wù)之間的一種注銷機制,應(yīng)用場景不多,這里也不詳細解釋了。這里重點關(guān)注一下Front-Channel Logout這個規(guī)范(http://openid.net/specs/openid-connect-frontchannel-1_0.html),它的使用最為廣泛,其工作的具體的流程如下(結(jié)合Session Management規(guī)范):

在上圖中的2和3屬于session management這個規(guī)范的一部。其中第2步中,odic的退出登錄的地址是通過Discovery服務(wù)中返回的end_session_endpoint字段提供的RP的。其中還有一個check_session_iframe字段則是供純前端的js應(yīng)用來檢查oidc的登錄狀態(tài)用的。

4567這四步則是屬于front-channel logout規(guī)范的一部分,OIDC服務(wù)的支持情況在Discovery服務(wù)中也有對應(yīng)的字段描述:

4567這一部分中重點有兩個信息:
- RP退出登錄的URL地址(這個在RP注冊的時候會提供給OIDC服務(wù));
- URL中的sessionid這個參數(shù),這個參數(shù)一般是會包含在idtoken中給到OIDC客戶端,或者在認證完成的時候以一個獨立的sessionid的參數(shù)給到OIDC客戶端,通常來講都是會直接把它包含在IDToken中以防止被篡改。
5 總結(jié)
本篇博客介紹了OIDC的發(fā)現(xiàn)服務(wù),OAuth2的兩個擴展規(guī)范,以及OIDC管理會話的機制。至此則可以構(gòu)成一個完整的認證和退出的流程。其中有一點需要特別注意,這個流程中用到的token是OIDC定義的IDToken,IDToken,IDToken(重要要的事情說三遍),而不是OAuth2中定義的Access Token,千萬不要混淆這兩者,它們是有著本質(zhì)的區(qū)別的(這一點在[認證授權(quán)] 3.基于OAuth2的認證(譯)和[認證授權(quán)] 4.OIDC(OpenId Connect)身份認證授權(quán)(核心部分)中都有解釋)。
6 Example
筆者基于IdentityServer3和IdentitySever4(兩者都是基于OIDC的一個.NET版本的開源實現(xiàn))寫的一個集成SSO,API訪問授權(quán)控制,GIthub,QQ登錄(作為IDP)的demo:https://github.com/linianhui/oidc.example 。
參考
oidc : http://openid.net/connect/
oidc - discovery :http://openid.net/specs/openid-connect-discovery-1_0.html
oauth2 - multiple-response-types :http://openid.net/specs/oauth-v2-multiple-response-types-1_0.html
oauth2 - form-post-response-mode :http://openid.net/specs/oauth-v2-form-post-response-mode-1_0.html
oidc - session-menagement :http://openid.net/specs/openid-connect-session-1_0.html
oidc - front-channel-logout :http://openid.net/specs/openid-connect-frontchannel-1_0.html
浙公網(wǎng)安備 33010602011771號