認(rèn)證與授權(quán)協(xié)議對比:OAuth2、OpenID、SMAL 以及OIDC

認(rèn)證(authenticate)授權(quán)(authorize)是倆個容易被弄混的概念,尤其是只看英文。

認(rèn)證意味著證實某個用戶是他所聲明的那個人;授權(quán)意味決定一個身份確定的用戶能夠訪問哪些資源。

認(rèn)證授權(quán)是目前大多數(shù)系統(tǒng)都必須要實現(xiàn)的功能,認(rèn)證就是驗證用戶的身份,授權(quán)就是驗證身份后對受限資源的訪問控制。最開始是單個平臺要做,后來在互聯(lián)網(wǎng)時代到來,一個賬戶可登陸多個平臺,然后是各種開放平臺賬戶共享,認(rèn)證授權(quán)變得越來越重要。關(guān)于驗證授權(quán)方面的規(guī)范協(xié)議也相對成熟通用。

單店登錄和統(tǒng)一認(rèn)證中主要三個協(xié)議是OpenID、OAuthSAML被稱為單點登錄的三駕馬車。

最早出現(xiàn)的認(rèn)證授權(quán)協(xié)議是SMAL,一般用在企業(yè)級單點登錄場景。平時接觸到的不多。

OAuth是看到的用的比較多的認(rèn)證協(xié)議,尤其是在API認(rèn)證授權(quán)時用,最開始是1.0版本,后來因為有會話共計、會話劫持的漏洞,除了1.0a版本,但編程實現(xiàn)較麻煩,后來出現(xiàn)OAuth2版本,但不兼容之前的版本。一般見到大多數(shù)時用的是OAuth2.

OpenId一開始出現(xiàn)是為了解決認(rèn)證的問題,后來出現(xiàn)了OpenId Connect,在OAuth的基礎(chǔ)上也可以實現(xiàn)授權(quán)的功能。

對比點 OAuth2 OpenId SMAL
票據(jù)格式 JSON or SAML2 JSON XML
支持授權(quán) Yes No Yes
支持認(rèn)證 偽認(rèn)證 Yes Yes
創(chuàng)建年份 2005 2006 2001
最新版本 OAuth2 OpenID Connect SAML2.0
傳輸方式 HTTP HTTP GET and HTTP POST HTTP重定向,SAML SOAP綁定 ,HTTP POST綁定
安全弱點 不能抵抗網(wǎng)絡(luò)釣魚,OAyth沒有使用數(shù)據(jù)簽名和加密等措施,數(shù)據(jù)安全完全依賴TLS 不能抵抗網(wǎng)絡(luò)釣魚,一個釣魚的IDP如果惡意記錄下來用戶的OpenID,將會造成很嚴(yán)重的隱私安全問題。 XML簽名存在漏洞,可能被偽造。
使用場景 API授權(quán) 商用應(yīng)用的單店登錄 企業(yè)級的單店登錄,但是對于移動端支持不是很好。

SAML2.0協(xié)議

SAML,全稱為Security Assertion Markup Language,是一種用于安全性斷言的標(biāo)記語言,目前最新版本是2.0。

SAML在單點登錄中大有用處:在SAML協(xié)議中,一旦用戶身份被主網(wǎng)站(身份鑒別服務(wù)器,Identity Provider,IDP)認(rèn)證過后,該用戶再去范文其他在主網(wǎng)站注冊過的應(yīng)用(服務(wù)提供者,Service Providers,SP)時,都可以直接登錄,而不用在輸入身份和口令。

SAML協(xié)議的核心是:IDP和SP通過用戶的瀏覽器的重定向訪問來實現(xiàn)交換數(shù)據(jù)。

SP向IDP發(fā)出SAML身份認(rèn)證請求消息,來請求IDP鑒別用戶身份;IDP向用戶索要用戶名和口令,并驗證其是否正確,如果驗證無誤,則想SP返回SAML身份認(rèn)證應(yīng)答,表示該用戶已經(jīng)登錄成功了,此外應(yīng)答中還包括一些額外的信息,來確保應(yīng)答不被篡改和偽造。

下面我們以用戶登錄SP,SP向IDP發(fā)起求情來確認(rèn)用戶身份微粒子,看看SAML的工作流程。比如SP是Google的Apps,IDP是一所大學(xué)的身份服務(wù)器,Alice是該大學(xué)的一名學(xué)生。

SAML認(rèn)證流程

現(xiàn)在Alice要通過瀏覽器查閱她的郵件,Alice一般會通過瀏覽器訪問一個網(wǎng)頁,比如https://mail.google.com/a/my-university.nl.因為這是個聯(lián)合身份域,所以Google不會向用戶索取用戶名和密碼,而是將其重定向到IDP來認(rèn)證其身份。用戶被重定向的URL類似于這種:

https://idp:uni.nl/sso?SAMLRequest=fVLLTuswEN0j8Q...C%3D

嵌入到HTTP請求中的SAMLRequest就是SAML認(rèn)證請求消息。因為SAML是基于XML的(通常比較長),完整認(rèn)證求情消息要經(jīng)過壓縮(為Url節(jié)省空間)和編碼(防止特殊字符)才能傳輸。在壓縮和編碼之前,SAML消息有如下格式:

<AuthnRequest  ID="kfcn...lfki" 
  Version="2.0" 
  IssueInstant="2013-02-05T08:28:50Z" 
  ProtocolBinding="urn:oasis:names:tc:SAML: 2.0:bindings:HTTP-POST" 
  ProviderName="google.com" 
  AssertionConsumerServiceURL="https://www.google.com/a/uni.nl/acs">
  <Issuer>google.com</Issuer>
  <NameIDPolicy  AllowCreate="true"
    Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"/>;
</AuthnRequest>;

上面的內(nèi)容用最直白的方式解釋出來就是:這個來自Google的求情,請驗證當(dāng)前用戶身份,并將結(jié)果返回

當(dāng)IDP收到消息并確認(rèn)要接受認(rèn)證求情之后,就會要求Alice輸入用戶名和口令來驗證其身份(如果Alice已經(jīng)登陸過了,就會跳過該步驟);當(dāng)驗證通過之后,Alice的瀏覽器將會跳轉(zhuǎn)回google的特定頁面(AssertionConsumerService 簡稱ACS)。同樣,SAML身份認(rèn)證響應(yīng)的內(nèi)容也是在壓縮并編碼后以參數(shù)形式傳輸。在壓縮和編碼之前,其結(jié)構(gòu)如下:

<Response Version="2.0" 
  IssueInstant="2013-02-05T08:29:00Z" 
  Destination="https://www.google.com/a/my.uni.nl/acs" InResponseTo="kfcn...lfki">   
  <Issuer>https://idp.uni.nl/</Issuer>   
  <Status>
    <StatusCode   
      Value="urn:oasis:names:tc:SAML:2.0:status:Success"/> 
  </Status> 
  <Assertion Version="2.0" 
    IssueInstant="2013-02-05T08:29:00Z">     
    <Issuer>https://idp.uni.nl/</Issuer>   
    <Subject> 
      <NameID>alice</NameID>   
      <SubjectConfirmation ...> 
        <SubjectConfirmationData 
          NotOnOrAfter="2013-02-05T08:34:00Z"   
          Recipient="https://www.google.com/a/my.uni.nl/acs" InResponseTo="kfcn...lfki"/>  
        </SubjectConfirmation> 
    </Subject> 
    <Conditions NotBefore="2013-02-05T08:28:30Z" NotOnOrAfter="2013-02-05T08:34:00Z"> 
    </Conditions> 
    <AuthnStatement 
      AuthnInstant="2013-02-05T08:29:00Z" 
      SessionNotOnOrAfter="2013-02-05T16:29:00Z> 
    </AuthnStatement> 
  </Assertion>
 </Response>

雖然內(nèi)容很多,但是其主要表達(dá)的是:該消息來自idp.uni.nl,名為Alice的用戶身份已經(jīng)被我驗證,該消息的有效期分2分鐘,此外重定向的URL中還要有該消息的簽名以保證其不被篡改,驗證簽名的公鑰和算法,都是IDP和SP提前協(xié)商好的。

當(dāng)Google接受到SAML認(rèn)證相應(yīng)之后,會首先驗證消息的簽名是否正確以及是否超時失效,然后再從認(rèn)證消息中提取出Google能識別用戶身份(NameId 即Alice)如果以上的步驟都是順利的,用戶將會成功登陸Google。

為了便于解釋,以上例子中的信息都保持可讀性,如果想要去看看真實的SAML信息,建議使用火狐瀏覽器的插件工具SAML tracer。該插件將會在瀏覽器中添加一個窗口來顯示SAML消息,一下是截圖。


SAML tracer

參考

http://www.itdecent.cn/p/636c1ee16eba


OAuth2.0協(xié)議

協(xié)議中的各種角色:應(yīng)用、API和用戶

  • 第三方應(yīng)用:客戶端。即嘗試去獲得用戶賬戶信息的應(yīng)用,用戶需要先對此操作授權(quán)。
  • API:資源服務(wù)器,提供用來獲得用戶信息的API。
  • 授權(quán)服務(wù)器:讓用戶同意或者拒絕訪問請求。在某些情況下,授權(quán)服務(wù)器和API資源服務(wù)器會是同一個,但是在大多數(shù)情況下,二者是獨立的。
  • 用戶:資源的擁有者,當(dāng)前請求正在嘗試獲得他們賬戶的部分信息。

創(chuàng)建App

在開始OAuth流程之前,首先需要注冊一個新應(yīng)用到服務(wù)器。通常在注冊的過程中,需要提供應(yīng)用的基本信息,比如應(yīng)用名稱、網(wǎng)站信息、logo等等。此外,你還需要注冊一個重定向URI,用以將用戶通過瀏覽器或者移動客戶端重定向回Web服務(wù)器,這個URI很重要。

重定向URI

服務(wù)器只會把用戶重定向回注冊過的URI以避免有些安全攻擊。任何HTTP的重定向請求都必須會用TLS保護(hù),所以要求使用HTTPS。這樣的要求是為了防止token在傳輸過程中被截獲。對于原生APP,重定向的URI可以被注冊為一個自定義的URL scheme,比如:

demoapp://redirect
Client ID & Secret

當(dāng)注冊完畢之后,一般會返回給用戶一個客戶端ID(Client ID)和一個客戶端秘鑰(Client Secret)。這個ID一般是公開的信息,用來構(gòu)造登錄URL,或者被包含在頁面的JS代碼中。這個秘鑰必須是保密的。如果一個已經(jīng)部署的應(yīng)用不能保護(hù)秘鑰,比如一個簡單的JS網(wǎng)頁,則不應(yīng)該使用客戶端秘鑰,同時理論上服務(wù)器也不應(yīng)該向這類應(yīng)用頒發(fā)秘鑰。

授權(quán) 得到授權(quán)碼

OAuth2 流程的第一步是獲得用戶的授權(quán)。對于基于瀏覽器應(yīng)用或是移動應(yīng)用,這一步通常是在服務(wù)器顯示給用戶的接口上完成的。

OAuth2 提供了多種授權(quán)模式,根據(jù)不同情況而使用。

  • 授權(quán)碼模式:適用于web應(yīng)用,瀏覽器應(yīng)用或是移動APP
  • 口令模式:適用于使用用戶名和口令登錄的模式
  • 應(yīng)用訪問模式:適用于應(yīng)用訪問
  • 默認(rèn)模式:之前被推薦,在沒有Secret的情況下使用,現(xiàn)在被沒有客戶端秘鑰的授權(quán)碼模式取代

Web 服務(wù)

Web服務(wù)是最常見的應(yīng)用類型。用戶所使用的Web App程序運(yùn)行在服務(wù)器端,其源碼不會公開暴露,這就代表著這類應(yīng)用在授權(quán)的過程中可以使用客戶端秘鑰(Client Secret),以避免某些攻擊手段。

授權(quán)

創(chuàng)建登錄鏈接,將用戶重定向到授權(quán)服務(wù)器:

https://oauth2server.com/auth?response_type=code&
 client_id=CLIENT_ID&redirect_uri=REDIRECT_URI&scope=photos&state=abcdef
  • code:代表服務(wù)器希望收到授權(quán)碼
  • client_id:注冊應(yīng)用時頒發(fā)的ID
  • redirect_uri:指明當(dāng)用戶授權(quán)完成之后返回的地址;
  • scope:一個或多個值,用來指明希望獲得用戶賬戶哪部分權(quán)限;
  • state:由應(yīng)用生成的一個隨機(jī)字符串,會在之后的過程中去驗證。

通過以上鏈接,用戶將看到如下的界面


IDP的授權(quán)頁面

當(dāng)用戶點擊allow后,授權(quán)服務(wù)器會把用戶重定向回應(yīng)用網(wǎng)站,并在連接中帶上授權(quán)碼

https://oauth2client.com/cb?code=AUTH_CODE_HERE&state=abcdef
  • code:IDP服務(wù)器返回的授權(quán)碼
  • state:返回請求授權(quán)碼過程中發(fā)送的state

當(dāng)應(yīng)用有接收到這個請求時,要首先驗證state是否就是應(yīng)用剛才發(fā)送的值。在發(fā)送state之后,可以吧state保存到Session以便于后序的比較。這樣做的目的是防止應(yīng)用接受任意偽造的授權(quán)碼。

換取Token

然后使用授權(quán)碼到資源服務(wù)器換取Token

POST https://api.oauth2server.com/token
  grant_type=authorization_code&
  code=AUTH_CODE_HERE&
  redirect_uri=REDIRECT_URI&
  client_id=CLIENT_ID&
  client_secret=CLIENT_SECRET
  • grant_type = authorization_code :代表授權(quán)模式為授權(quán)碼模式
  • code = AUTH_CODE_HERE:為上一步code中獲取的授權(quán)碼
  • redirect_uri = REDIRECT_URI 重定向URI
  • client_id = CLIENT_ID 注冊應(yīng)用時頒發(fā)的ID
  • client_secret=CLIENT_SECRET 客戶端秘鑰,因為當(dāng)前請求是服務(wù)器之間的傳輸,并沒有暴露給用戶。

IDP服務(wù)器會返回授權(quán)碼和有效期:

{
  "access_token":"RsT5OjbzRn430zqMLgV3Ia",
  "expires_in":3600
}

或者是授權(quán)失敗的提示

{
  "error":"invalid_request"
}

注意:服務(wù)器要求應(yīng)用必須提前注冊重定向的URI


口令模式

這種模式直接使用用戶名和密碼來取回token。很顯然,這種應(yīng)用去手機(jī)用戶的口令,所以之間以當(dāng)前的App是專門為服務(wù)器設(shè)計的情況下使用。

POST https://api.oauth2server.com/token
  grant_type=password&
  username=USERNAME&
  password=PASSWORD&
  client_id=CLIENT_ID
  • grant_type=password 指明使用口令模式
  • username=USERNAME 用戶名
  • password=PASSWORD 口令
  • client_id=CLIENT_ID client

資源服務(wù)器返回的Token和其他模式一樣。值得注意的是,因為口令模式多用于移動端和桌面應(yīng)用,使用secret并不合適。


應(yīng)用訪問模式

在一些情況下,是應(yīng)用去訪問服務(wù)器獲取資源。而不是某個用戶。比如應(yīng)用去獲取一些服務(wù)在應(yīng)用的配置信息,這些信息不屬于某個用戶的。這種情況下,應(yīng)用也需要被授權(quán),得到Token去訪問數(shù)據(jù),這就是應(yīng)用訪問模式的意義。
Oauth提供了Client_credentials模式來處理這個問題:

POST https://api.oauth2server.com/token
    grant_type=client_credentials&
    client_id=CLIENT_ID&
    client_secret=CLIENT_SECRET

資源服務(wù)器返回形式和其他模式是相同的。

創(chuàng)建已經(jīng)授權(quán)的請求

最后就是使用AccessToken獲取資源,如何表示一個請求已經(jīng)被授權(quán)?就是在Http頭中加入Token:

curl -H "Authorization: Bearer RsT5OjbzRn430zqMLgV3Ia" \
https://api.oauth2server.com/1/me

另外盡量確保使用Https通信,這樣才能保證信息安全。

與OAuth1.0版本差異

最后說明下兩個版本OAuth協(xié)議有什么不同點。

認(rèn)證和簽名

OAuth1.0流程中有大量密碼學(xué)上的簽名操作,以保證數(shù)據(jù)完整性;OAuth2 由Https來保護(hù)數(shù)據(jù)。

用戶體驗

和OAuth 1.0相比,OAuth 2在移動端的體驗更好。

性能

和OAuth 1.0相比,OAuth 2性能更好,減少了流程的步驟。

這里有一份很好理解的圖解:
【簡易圖解】『 OAuth2.0』 猴子都能懂的圖解
【簡易圖解】『 OAuth2.0』 『進(jìn)階』 授權(quán)模式總結(jié)

參考

http://www.itdecent.cn/p/6392420faf99


OpenID Connect協(xié)議

如果要談單點登錄和身份認(rèn)證,就不得不談OpenID Connect(OIDC).最典型的使用實例就是使用Google賬戶登陸其他應(yīng)用,這一經(jīng)典的協(xié)議模式,為其他廠商的第三方登陸起到了標(biāo)桿的作用。被廣泛參考和使用。

OpenID Connect簡介

OpenID Connect是基于OAuth2 規(guī)范族的客戶操作的身份驗證協(xié)議。他是用簡單的REST/JSON 消息流來實現(xiàn),和之前任何一種身份認(rèn)證協(xié)議相比,開發(fā)者可以輕松集成。

OpenID Connect允許開發(fā)者驗證跨網(wǎng)站和應(yīng)用的用戶,而無需擁有和管理密碼文件。
OpenID Connect允許索尼又類型的客戶,包括基于瀏覽器的JavaScript和本機(jī)移動應(yīng)用程序,啟動登錄流動和接收可驗證斷言對登錄用戶的身份。

OIDC基礎(chǔ)

簡要而言,OIDC是一種安全機(jī)制,用于應(yīng)用連接到身份認(rèn)證服務(wù)器(Identity Service)獲取用戶信息,并將這些信息以安全可靠的方法返回給應(yīng)用。

在最初因為OpenID經(jīng)常和OAuth協(xié)議一起提及,所以二者經(jīng)常被搞混。

  • OpenID 是Authentication,即認(rèn)證,對用戶的身份進(jìn)行認(rèn)證,判斷其身份是否有效,也就是讓網(wǎng)站知道“你是你聲稱的那個用戶”
  • OAuth是Authorization 即授權(quán),在已知用戶身份合法的情況下,經(jīng)用戶授權(quán)來允許某些操作,也就是讓網(wǎng)站知道“你能被允許做哪些事情”
    由此可知,授權(quán)要在認(rèn)證之后進(jìn)行,只有確定用戶身份之后才能授權(quán)

(身份認(rèn)證)+OAuth2.0 = OpenID Connect

OpenID Connect是“認(rèn)證”和“授權(quán)”的結(jié)果,因為其基于OAuth協(xié)議,所以O(shè)penID Connect協(xié)議中包含了client_id、client_secret還有redirect_uri等字段標(biāo)識。這些信息被保存在“身份認(rèn)證服務(wù)器”,以確保特定的客戶端收到的信息只來自于合法的應(yīng)用平臺。這樣做的目的是為了防止client_id泄露而造成的惡意網(wǎng)站發(fā)起的OIDC流程。

舉個栗子,某個用戶使用FaceBook的子應(yīng)用(例如faceBook中的某一款游戲),該應(yīng)用可以通過FaceBook賬號登錄,則你可以在應(yīng)用找那個發(fā)起請求到“身份認(rèn)證服務(wù)器”(也就是FaceBook的服務(wù)器)請求登錄,這時你會看到如下界面,詢問是否授權(quán)。

授權(quán)頁面

在OAuth中,這些授權(quán)被稱為scope.OpenID Connect也有自己特殊的scope--openid,他必須在第一次請求“身份鑒別服務(wù)器(Identity Provider簡稱IDP)”時發(fā)送過去。

OIDC 流程

OAuth2提供了Access Token來解決授權(quán)單方客戶端訪問受保護(hù)資源的問題;相似的,OIDC在這個基礎(chǔ)上提供了ID Token來解決第三方客戶端表示用戶身份認(rèn)證的問題。
OIDC的核心在于OAUth2的授權(quán)流程中,一并提供用戶的身份認(rèn)證信息(ID-Token),給到第三方客戶端,ID-Token使用JWT(JSON Web Token - 在Web應(yīng)用間安全地傳遞信息
)格式來包裝,得益于JWT的自包含性,緊湊型以及防篡改機(jī)制,是的ID-Token可以安全的傳遞給第三方客戶端程序并且容易被驗證。應(yīng)用服務(wù)器,在驗證ID-Token正確性后,使用Access-Token向UserInfo接口換取用戶的更多信息。

有上述可知,OIDC是遵循了OAuth協(xié)議流程,在申請Access-Token的同時,也返回了ID-Token來驗證用戶身份。

相關(guān)定義
  • EU:End User 用戶。
  • RP:Relying Party 用來代指OAuth2中受信任的客戶端,身份認(rèn)證和授權(quán)信息的消費方。
  • 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:用戶信息接口(受IAuth2保護(hù)),當(dāng)RP使用ID-Token訪問時,返回授權(quán)用戶的信息,此接口必須使用HTTPS。

下面我們來俺看OIDC的具體協(xié)議流程。
根據(jù)應(yīng)用客戶端不同,OIDC的工作模式月應(yīng)該是不同的。和OAuth類似,主要看是否客戶端能否保證client_secret的安全性。

如果是JS應(yīng)用,其所有的代碼都會被加載到瀏覽器而暴露出來,沒有后端可以保證client_secret的安全性,則需要使用默認(rèn)模式流程(Implicit Flow)

如果是傳統(tǒng)的客戶端應(yīng)用,后端代碼和用戶是隔離的保證client_secret不被泄漏。就可以使用授權(quán)碼模式流程(Authentication Flow).

此外還有混合模式流程(Hybird Flow),簡而言之就是以上二者的融合。

OAuth2中還有口令模式和應(yīng)用訪問模式 這兩種方式來獲取access Token,為什么OIDC中沒有擴(kuò)展這些方式呢?
口令模式是需要用戶提供賬號和密碼給RP的,既然都已經(jīng)有用戶名和密碼了,就不需要再獲取什么用戶身份了。至于應(yīng)用訪問模式,這種方式不需要用戶參與,也就無需要認(rèn)證和獲取用戶身份了。這也能反映出授權(quán)和認(rèn)證的差異,以及只是用OAuth2來做身份認(rèn)證的事情是遠(yuǎn)遠(yuǎn)不夠的,也是不合適的。

授權(quán)碼模式流程

授權(quán)碼模式流程

和OAuth認(rèn)證流程類似
1.RP發(fā)送一個認(rèn)證請求給OP,其中附帶client_id
2.OP對EU進(jìn)行身份認(rèn)證
3.OP返回響應(yīng),發(fā)送授權(quán)碼給RP
4.RP使用授權(quán)碼想OP索要ID-Token和Access-Token,OP驗證無誤后返回給RP;
5.RP使用Access-Token發(fā)送一個請求到UserInfo EndPoint;UserInfo EndPoint返回EU的Claims。

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

RP使用OAth2的Authorization-code的方式來完成用戶身份認(rèn)證,所有TOken都是通過OP的Token EndPoint來發(fā)放的。構(gòu)建一個OIDC的Authentication Request需要提供如下參數(shù):

  • scope:必須。OIDC的請求必須包含值為“openid”的scope參數(shù)。
  • response_type: 必選 同OAuth2
  • client_id: 必選。同OAuth2
  • redirect_uri:必選。同OAuth2
  • state:推薦 同OAuth2.防止CSRF,XSRF。

示例如下:

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)

在OP接收到認(rèn)證請求之后,需要對請求參數(shù)做嚴(yán)格的驗證,具體的規(guī)則參見http://openid.net/specs/openid-connect-core-1_0.html#AuthRequestValidation,驗證通過后引導(dǎo)EU進(jìn)行身份認(rèn)證并且同意授權(quán)。在這一切都完成后,會重定向到RP指定的回調(diào)地址(redirect_uri),并且把code和state參數(shù)傳遞過去。比如:

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

獲取ID Token

RP使用上一步獲得的code來請求TOken EndPoint,這一步同OAuth2,就不再展開細(xì)說了。然后Token EndPoint會返回響應(yīng)的Token,其中除了OAuth2規(guī)定的部分?jǐn)?shù)據(jù)外,還會附加一個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)行驗證(具體規(guī)則參見http://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidationhttp://openid.net/specs/openid-connect-core-1_0.html#ImplicitTokenValidation)。至此,可以說用戶身份認(rèn)證就可以完成了。后序可以根據(jù)UserInfo EndPoint獲取更完整的信息。

安全令牌 ID-Token

上面提到過OIDC對OAuth2最主要的擴(kuò)展就是提供了ID-Token,下面我們來看看ID-Token的主要構(gòu)成:

  • iss = Issuer Identifier:必須。提供認(rèn)證信息者的唯一標(biāo)識。一般是Url的host+path部分
  • sub = Subject Identifier:必須。iss提供EU的唯一標(biāo)識;最長為255個ASCII個字符;
  • aud = Audience(s):必須。標(biāo)識ID-Token的受眾。必須包含OAuth2的client_id;
  • exp =Expiration time:必須。ID-Token的過期時間。
  • iat = Issued At Time。必須。JWT構(gòu)建的時間。
  • auth_time = AuthenticationTime:EU完成認(rèn)證的時間。如果RP發(fā)送認(rèn)證請求的時候攜帶max_age的參數(shù),則此Claim是必須的。
  • nonce:RP發(fā)送請求的時候提供的隨機(jī)字符串,用來減緩重放攻擊,也可以來關(guān)聯(lián)ID-Token和RP本身的Session信息。
  • acr = Authentication Context Class Reference:可選。表示一個認(rèn)證上下文引用值,可以用來標(biāo)識認(rèn)證上下文類。
  • amr = Authentication Methods References:可選。表示一組認(rèn)證方法。
  • azp = Authorized party:可選。結(jié)合aud使用。只有在被認(rèn)證的一方和受眾(aud)不一致時才使用此值,一般情況下很少使用。
{
   "iss": "https://server.example.com",
   "sub": "24400320",
   "aud": "s6BhdRkqt3",
   "nonce": "n-0S6_WzA2Mj",
   "exp": 1311281970,
   "iat": 1311280970,
   "auth_time": 1311280969,
   "acr": "urn:mace:incommon:iap:silver"
  }

另外ID Token必須使用JWT進(jìn)行簽名和JWE(JSON Web Encryption)加密。從而提供認(rèn)證的完整性、不可否認(rèn)性以及可選的保密性。

USerInfo EndPoint

可能有的讀者發(fā)現(xiàn)了,ID-Token只有sub是EU相關(guān)的,這在一般情況下是不夠的,必須還需要EU的用戶名,頭像等其他的資料,OIDC提供了一組公共的cliams,來提供更多用戶的信息,這就是UserInfo EndPoint。

在RP得到Access Token后可以請求此資源,然后獲得一組EU相關(guān)的Claims,這些信息可以說是ID-Token的擴(kuò)展,ID-Token中只需包含EU的唯一標(biāo)識sub即可(避免ID-Token過于龐大和暴露用戶敏感信息),然后再通過此接口獲取完整的EU的信息。此資源必須部署在TLS之上(即必須使用HTTPS)例如:

  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"
  }

其中sub代表EU的唯一標(biāo)識,這個claim是必須的,其他都是可選的。

參考

http://www.itdecent.cn/p/be7cc032a4e9

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容