1. 程式人生 > >[認證授權] 4.OIDC(OpenId Connect)身份認證授權(核心部分)

[認證授權] 4.OIDC(OpenId Connect)身份認證授權(核心部分)

1 什麼是OIDC?

OpenID Connect 1.0 is a simple identity layer on top of the OAuth 2.0 protocol. It allows Clients to verify the identity of the End-User based on the authentication performed by an Authorization Server, as well as to obtain basic profile information about the End-User in an interoperable and REST-like manner.

OpenID Connect allows clients of all types, including Web-based, mobile, and JavaScript clients, to request and receive information about authenticated sessions and end-users. The specification suite is extensible, allowing participants to use optional features such as encryption of identity data, discovery of OpenID Providers, and session management, when it makes sense for them.

簡單來說:OIDC是OpenID Connect的簡稱,OIDC=(Identity, Authentication) + OAuth 2.0。它在OAuth2上構建了一個身份層,是一個基於OAuth2協議的身份認證標準協議。我們都知道OAuth2是一個授權協議,它無法提供完善的身份認證功能(關於這一點請參考[認證授權] 3.基於OAuth2的認證(譯)),OIDC使用OAuth2的授權伺服器來為第三方客戶端提供使用者的身份認證,並把對應的身份認證資訊傳遞給客戶端,且可以適用於各種型別的客戶端(比如服務端應用,移動APP,JS應用),且完全相容OAuth2,也就是說你搭建了一個OIDC的服務後,也可以當作一個OAuth2的服務來用。應用場景如圖:

理解OIDC的前提是需要理解OAuth2,這裡假設大家都有OAuth2的基礎,不清楚的可以先閱讀本系列的前幾篇OAuth2的文章。

2 OIDC 協議族

OIDC本身是有多個規範構成,其中包含一個核心的規範,多個可選支援的規範來提供擴充套件支援,簡單的來看一下:

  1. Core:必選。定義OIDC的核心功能,在OAuth 2.0之上構建身份認證,以及如何使用Claims來傳遞使用者的資訊。
  2. Discovery:可選。發現服務,使客戶端可以動態的獲取OIDC服務相關的元資料描述資訊(比如支援那些規範,介面地址是什麼等等)。
  3. Dynamic Registration :可選。動態註冊服務,使客戶端可以動態的註冊到OIDC的OP(這個縮寫後面會解釋)。
  4. OAuth 2.0 Form Post Response Mode:可選。針對OAuth2的擴充套件,OAuth2回傳資訊給客戶端是通過URL的querystring和fragment這兩種方式,這個擴充套件標準提供了一基於form表單的形式把資料post給客戶端的機制。
  5. Session Management :可選。Session管理,用於規範OIDC服務如何管理Session資訊。
  6. Front-Channel Logout:可選。基於前端的登出機制,使得RP(這個縮寫後面會解釋)可以不使用OP的iframe來退出。
  7. Back-Channel Logout:可選。基於後端的登出機制,定義了RP和OP直接如何通訊來完成登出。

除了上面這8個之外,還有其他的正在制定中的擴充套件。看起來是挺多的,不要被嚇到,其實並不是很複雜,除了Core核心規範內容多一點之外,另外7個都是很簡單且簡短的規範,另外Core是基於OAuth2的,也就是說其中很多東西在複用OAuth2,所以說你理解了OAuth2之後,OIDC就是非常容易理解的了,我們這裡就只關注OIDC引入了哪些新的東西(Core,其餘7個可選規範不做介紹,但是可能會提及到)。千言萬語都不如一張圖,沒圖你說個***。

上圖是官方給出的一個OIDC組成結構圖,我們暫時只關注Core的部分,其他的部分了解是什麼東西就可以了,當作黑盒來用。就像當初的AJAX一樣,它其實並不是一個新的技術,而是結合很多已有的技術,按照規範的方式組合起來,就是AJAX。同理,OIDC也不是新技術,它主要是借鑑OpenId的身份標識,OAuth2的授權和JWT包裝資料的方式,把這些技術融合在一起就是OIDC。

3 OIDC 核心概念

OAuth2提供了Access Token來解決授權第三方客戶端訪問受保護資源的問題;OIDC在這個基礎上提供了ID Token來解決第三方客戶端標識使用者身份認證的問題。OIDC的核心在於在OAuth2的授權流程中,一併提供使用者的身份認證資訊(ID Token)給到第三方客戶端,ID Token使用JWT格式來包裝,得益於JWT(JSON Web Token)的自包含性,緊湊性以及防篡改機制,使得ID Token可以安全的傳遞給第三方客戶端程式並且容易被驗證。此外還提供了UserInfo的介面,使用者獲取使用者的更完整的資訊。

3.1 OIDC 主要術語

  1. EU:End User:一個人類使用者。
  2. RP:Relying Party ,用來代指OAuth2中的受信任的客戶端,身份認證和授權資訊的消費方;
  3. OP:OpenID Provider,有能力提供EU認證的服務(比如OAuth2中的授權服務),用來為RP提供EU的身份認證資訊;
  4. ID Token:JWT格式的資料,包含EU身份認證的資訊。
  5. UserInfo Endpoint:使用者資訊介面(受OAuth2保護),當RP使用Access Token訪問時,返回授權使用者的資訊,此介面必須使用HTTPS。

3.2 OIDC 工作流程

從抽象的角度來看,OIDC的流程由以下5個步驟構成:

  1. RP傳送一個認證請求給OP;
  2. OP對EU進行身份認證,然後提供授權;
  3. OP把ID Token和Access Token(需要的話)返回給RP;
  4. RP使用Access Token傳送一個請求UserInfo EndPoint;
  5. UserInfo EndPoint返回EU的Claims。

上圖取自Core規範文件,其中AuthN=Authentication,表示認證;AuthZ=Authorization,代表授權。注意這裡面RP發往OP的請求,是屬於Authentication型別的請求,雖然在OIDC中是複用OAuth2的Authorization請求通道,但是用途是不一樣的,且OIDC的AuthN請求中scope引數必須要有一個值為的openid的引數(後面會詳細介紹AuthN請求所需的引數),用來區分這是一個OIDC的Authentication請求,而不是OAuth2的Authorization請求。

3.3 ID Token

上面提到過OIDC對OAuth2最主要的擴充套件就是提供了ID Token。ID Token是一個安全令牌,是一個授權伺服器提供的包含使用者資訊(由一組Cliams構成以及其他輔助的Cliams)的JWT格式的資料結構。ID Token的主要構成部分如下(使用OAuth2流程的OIDC)。

  1. iss = Issuer Identifier:必須。提供認證資訊者的唯一標識。一般是一個https的url(不包含querystring和fragment部分)。
  2. sub = Subject Identifier:必須。iss提供的EU的標識,在iss範圍內唯一。它會被RP用來標識唯一的使用者。最長為255個ASCII個字元。
  3. aud = Audience(s):必須。標識ID Token的受眾。必須包含OAuth2的client_id。
  4. exp = Expiration time:必須。過期時間,超過此時間的ID Token會作廢不再被驗證通過。
  5. iat = Issued At Time:必須。JWT的構建的時間。
  6. auth_time = AuthenticationTime:EU完成認證的時間。如果RP傳送AuthN請求的時候攜帶max_age的引數,則此Claim是必須的。
  7. nonce:RP傳送請求的時候提供的隨機字串,用來減緩重放攻擊,也可以來關聯ID Token和RP本身的Session資訊。
  8. acr = Authentication Context Class Reference:可選。表示一個認證上下文引用值,可以用來標識認證上下文類。
  9. amr = Authentication Methods References:可選。表示一組認證方法。
  10. azp = Authorized party:可選。結合aud使用。只有在被認證的一方和受眾(aud)不一致時才使用此值,一般情況下很少使用。

ID Token通常情況下還會包含其他的Claims(畢竟上述claim中只有sub是和EU相關的,這在一般情況下是不夠的,必須還需要EU的使用者名稱,頭像等其他的資料,OIDC提供了一組公共的cliams,請移步這裡http://openid.net/specs/openid-connect-core-1_0.html#StandardClaims)。另外ID Token必須使用JWS進行簽名和JWE加密,從而提供認證的完整性、不可否認性以及可選的保密性。一個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   }

3.4 認證

解釋完了ID Token是什麼,下面就看一下OIDC如何獲取到ID Token,因為OIDC基於OAuth2,所以OIDC的認證流程主要是由OAuth2的幾種授權流程延伸而來的,有以下3種:

  1. Authorization Code Flow:使用OAuth2的授權碼來換取Id Token和Access Token。
  2. Implicit Flow:使用OAuth2的Implicit流程獲取Id Token和Access Token。
  3. Hybrid Flow:混合Authorization Code Flow+Implici Flow。

這裡有個小問題大家可以思考下,OAuth2中還有基於Resource Owner Password Credentials Grant和Client Credentials Grant的方式來獲取Access Token,為什麼OIDC沒有擴充套件這些方式呢?

Resource Owner Password Credentials Grant是需要用途提供賬號密碼給RP的,賬號密碼給到RP了,還要什麼自行車(ID Token)。。。

Client Credentials Grant這種方式根本就不需要使用者參與,更談不上使用者身份認證了。這也能反映授權和認證的差異,以及只使用OAuth2來做身份認證的事情是遠遠不夠的,也是不合適的。

3.4.1 基於Authorization Code的認證請求

這種方式使用OAuth2的Authorization Code的方式來完成使用者身份認證,所有的Token都是通過Token EndPoint(OAuth2中定義:https://tools.ietf.org/html/rfc6749#section-3.2)來發放的。構建一個OIDC的Authentication Request需要提供如下的引數:

  1. scope:必須。OIDC的請求必須包含值為“openid”的scope的引數。
  2. response_type:必選。同OAuth2。
  3. client_id:必選。同OAuth2。
  4. redirect_uri:必選。同OAuth2。
  5. state:推薦。同OAuth2。防止CSRF, XSRF。

以上這5個引數是和OAuth2相同的。除此之外,還定義瞭如下的引數:

  1. response_mode:可選。OIDC新定義的引數(OAuth 2.0 Form Post Response Mode),用來指定Authorization Endpoint以何種方式返回資料。
  2. nonce:可選。ID Token中的出現的nonce就是來源於此。
  3. display : 可選。指示授權伺服器呈現怎樣的介面給EU。有效值有(page,popup,touch,wap),其中預設是page。page=普通的頁面,popup=彈出框,touch=支援觸控的頁面,wap=移動端頁面。
  4. prompt:可選。這個引數允許傳遞多個值,使用空格分隔。用來指示授權伺服器是否引導EU重新認證和同意授權(consent,就是EU完成身份認證後的確認同意授權的頁面)。有效值有(none,login,consent,select_account)。none=不實現現任何認證和確認同意授權的頁面,如果沒有認證授權過,則返回錯誤login_required或interaction_required。login=重新引導EU進行身份認證,即使已經登入。consent=重新引導EU確認同意授權。select_account=假如EU在授權伺服器有多個賬號的話,允許EU選擇一個賬號進行認證。
  5. max_age:可選。代表EU認證資訊的有效時間,對應ID Token中auth_time的claim。比如設定是20分鐘,則超過了時間,則需要引導EU重新認證。
  6. ui_locales:可選。使用者介面的本地化語言設定項。
  7. id_token_hint:可選。之前發放的ID Token,如果ID Token經過驗證且是有效的,則需要返回一個正常的響應;如果有誤,則返回對應的錯誤提示。
  8. login_hint:可選。向授權伺服器提示登入識別符號,EU可能會使用它登入(如果需要的話)。比如指定使用使用者使用blackheart賬號登入,當然EU也可以使用其他賬號登入,這只是類似html中input元素的placeholder。
  9. acr_values:可選。Authentication Context Class Reference values,對應ID Token中的acr的Claim。此引數允許多個值出現,使用空格分割。

以上是基於Authorization Code方式的OIDC的認證請求所需的引數。在OIDC的其他認證流程中也會有其他的引數或不同的引數值(稍有差異)。一個簡單的示例如下:

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

也可以是一個基於302的重定向方式。

3.4.2 基於Authorization Code的認證請求的響應

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

3.4.3 獲取ID Token

RP使用上一步獲得的code來請求Token EndPoint,這一步同OAuth2,就不再展開細說了。然後Token EndPoint會返回響應的Token,其中除了OAuth2規定的部分資料外,還會附加一個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"
  }

3.4.4 Implicit Flow和Hybrid Flow

Implicit Flow的工作方式是在OAuth2 Implicit Flow上附加提供id_token,當然,認證請求的引數和基於Authorization Code的流程稍有不同,具體的差異參見http://openid.net/specs/openid-connect-core-1_0.html#ImplicitAuthRequest,這裡就不做詳細介紹了。

Hybrid Flow則=Authorization Code Flow+Implicit Flow,也不再詳細介紹了。

3.5 UserInfo Endpoint

UserIndo EndPoint是一個受OAuth2保護的資源。在RP得到Access Token後可以請求此資源,然後獲得一組EU相關的Claims,這些資訊可以說是ID Token的擴充套件,比如如果你覺得ID Token中只需包含EU的唯一標識sub即可(避免ID Token過於龐大),然後通過此介面獲取完整的EU的資訊。此資源必須部署在TLS之上,例如:

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

成功之後響應如下:

  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": "[email protected]",
   "picture": "http://example.com/janedoe/me.jpg"
  }

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

4 總結

繼OAuth2之後,感覺OIDC也要大放異彩了。其本身是一個完全開放的標準,而且相容眾多的已有的IDP(身份提供商),比如基於SAML的、基於WS-Federation的等等已有的身份認證系統,都可以作為OIDC的OP存在。總結一下OIDC有那些特性和好處吧:

  1. OIDC使得身份認證可以作為一個服務存在。
  2. OIDC可以很方便的實現SSO(跨頂級域)。
  3. OIDC相容OAuth2,可以使用Access Token控制受保護的API資源。
  4. OIDC可以相容眾多的IDP作為OIDC的OP來使用。
  5. OIDC的一些敏感介面均強制要求TLS,除此之外,得益於JWT,JWS,JWE家族的安全機制,使得一些敏感資訊可以進行數字簽名、加密和驗證,進一步確保整個認證過程中的安全保障。

以上內容均是個人的一些理解,如果錯誤之處,歡迎指正!

5 Example

筆者基於IdentityServer3和IdentitySever4(兩者都是基於OIDC的一個.NET版本的開源實現)寫的一個整合SSO,API訪問授權控制,QQ聯合登陸(作為OP)的demo:https://github.com/linianhui/oidc.example 。

6 參考

官方資料:

案例:

相關推薦

[認證授權] 4.OIDCOpenId Connect身份認證授權核心部分

1 什麼是OIDC? OpenID Connect 1.0 is a simple identity layer on top of the OAuth 2.0 protocol. It allows Clients to verify the identity of the End-User ba

[認證授權] 5.OIDCOpenId Connect身份認證授權擴充套件部分

在上一篇[認證授權] 4.OIDC(OpenId Connect)身份認證授權(核心部分)中解釋了OIDC的核心部分的功能,即OIDC如何提供id token來用於認證。由於OIDC是一個協議族,如果只是簡單的只關注其核心部分其實是不足以搭建一個完整的OIDC服務的。本篇則解釋下OIDC中比較常用的幾個相關擴

ASP.NET Core的身份認證框架IdentityServer49-使用OpenID Connect新增使用者認證

原文: ASP.NET Core的身份認證框架IdentityServer4(9)-使用OpenID Connect新增使用者認證 OpenID Connect OpenID Connect 1.0是OAuth 2.0協議之上的一個簡單的身份層。 它允許客戶端基於授權伺服器執行的身份驗證來驗證終端使用者的

基於OIDCOpenID Connect的SSO

在[認證授權]系列部落格中,分別對OAuth2和OIDC在理論概念方面進行了解釋說明,其間雖然我有寫過一個完整的示例(https://github.com/linianhui/oidc.example),但是卻沒有在實踐方面做出過解釋。在這裡新開一個系列部落格,來解釋其各種不同的應用場景。因為OIDC是在

ASP.NET Core 認證授權[3]:OAuth & OpenID Connect認證

原文: ASP.NET Core 認證與授權[3]:OAuth & OpenID Connect認證 在上一章中,我們瞭解到,Cookie認證是一種本地認證方式,通常認證與授權都在同一個服務中,也可以使用Cookie共享的方式分開部署,但侷限性較大,而如今隨著微服務的流行,更加偏向於將以前的單體應用

Identity Server 4 預備知識 -- OpenID Connect 簡介

這篇文章我要介紹一下 OpenID Connect. OAuth 2.0 不是身份認證協議 OAuth 2.0 不是身份認證(Authentication)協議. 為什麼有人會認為OAuth 2.0具有身份認證的功能? 這是因為OAuth2經常作為身份認證(Authentication)協議的一部分來

413day版心三個模組中的左中部分

《2018年11月21日》【連續413天】 標題:版心三個模組中的左中部分; 內容: <!-- 左部分 --> <div class="jd-clo1"> <ul> <li><a href="#"

主流瀏覽器核心介紹前端開發值得了解的瀏覽器核心歷史

核心 首先得搞懂瀏覽器核心究竟指的是什麼。 瀏覽器核心又可以分成兩部分:渲染引擎(layout engineer 或者 Rendering Engine)和 JS 引擎。它負責取得網頁的內容(HTML、XML、影象等等)、整理訊息(例如加入 CSS 等),以及計算網頁的顯示方式,然後會輸出至顯示器或印

mybatis使用foreach批次插入,解決sequence只查詢一次的問題在此,我只看union all 部分

oracle的批量插入方式是: insert  into db(id, zgbh, shbzh)         select '1', '2', '3' from dual         union all select '2', '3', '4' from dual

Android 開發 知曉各種id資訊獲取執行緒ID、activityID、核心ID

/** * Returns the identifier of this process's user. * 返回此程序的使用者的識別符號。 */ Log.e(TAG, "Process.myUid() = " + android.os.Proces

簡易圖書館借還書系統核心部分

【第一題】 源程式: /*假設圖書館的圖書包含書名、編號和作者屬性,讀者包含姓名和借書證號屬性,每個讀者最多可借5本書。設計一個類object,從它派生出圖書類Book和讀者類Reader,在Reader類中有一個 rentbook()成員函式用於借閱圖書。主函式進行測試。說

OpenID Connect Core 1.0使用授權碼流驗證

3.1 使用授權碼流驗證(Authentication using the Authorization Code Flow) 本節描述如何使用授權碼流執行驗證。當使用授權碼流時,會從令牌終結點返回的所有令牌。 授權碼流返回授權碼給客戶端,這個授權碼可以直接交換一個ID T

OpenID Connect Core 1.0介紹

pairwise color 類型 客戶端 itu-t endpoint nta 框架 方式 IdentityServer4是基於OpenID Connect and OAuth 2.0框架,OpenID Connect Core 1.0是IdentityServer4最重

OpenID Connect Core 1.0ID Token

不同的 可能 indent ext mon 來源 conn 請求 引用 2、ID Token(ID Token) OpenID Connect主要是對OAuth 2.0 能夠使得終端用戶通過ID Token的數據結構進行驗證。當客戶端和潛在的其他請求聲明,ID Token包

OpenID Connect Core 1.0從第三方發起登入

在某些情況下,登入流程由一個OpenID提供者或其他方發起,而不是依賴方(RP)。在這種情況下,發起者重定向到RP在發起登入終結點,RP的請求驗證請求傳送到指定的OP。這個發起登入終結點可以在RP深度連結,而不是預設的登入頁面。RPs支援OpenID Connect Dynamic Client Regist

OpenID Connect Core 1.0聲明(Claims)

sil 額外 求一個 回聲 排序。 rfc6750 默認的配置 obj 什麽 5 聲明(Claims) 這一節說明客戶端如何獲取關於終端用戶聲明和驗證事件。它還定義了一組標準的基本聲明配置。預定義一組可請求的聲明,使用特定的scope值或能用於請求參數中的個人聲明。聲明可以

OpenID Connect Core 1.0使用隱式驗證流

3.2 使用隱式驗證流(Authentication using the Implicit Flow) 本節描述如何使用隱式流程執行驗證。使用隱式流程時,所有令牌從授權終結點返回;不使用令牌終結點返回。 隱式流程主要是由客戶在瀏覽器中使用指令碼語言實現。直接返回Access Token和ID Token到

CCF認證-201809-4 再買菜70分

    CCF認證-201809-4 思路:沒有很好的思路,就暴力了拿了70分,還沒有滿分,還會再更新的。   問題描述 試題編號: 201809-4 試題名稱: 再賣菜

阿里雲大資料ACP認證知識點梳理4——基礎SQL語句DDL部分

creat table page_view (user_id bigint,view_time bigint,page_url string,referrer_url string,ip string comment 'creat table sql') partitioned by (dt string,c

OpenID Connect Core 1.0宣告(Claims)

5 宣告(Claims) 這一節說明客戶端如何獲取關於終端使用者宣告和驗證事件。它還定義了一組標準的基本宣告配置。預定義一組可請求的宣告,使用特定的scope值或能用於請求引數中的個人宣告。宣告可以直接來自OpenID提供者或分散式來源。 5.1 標準宣告(Stand