看一下官方的介紹(http://openid.net/connect/):html
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.git
簡單來講:OIDC是OpenID Connect的簡稱,OIDC=(Identity, Authentication) + OAuth 2.0。它在OAuth2上構建了一個身份層,是一個基於OAuth2協議的身份認證標準協議。咱們都知道OAuth2是一個受權協議,它沒法提供完善的身份認證功能(關於這一點請參考[認證受權] 3.基於OAuth2的認證(譯)),OIDC使用OAuth2的受權服務器來爲第三方客戶端提供用戶的身份認證,並把對應的身份認證信息傳遞給客戶端,且能夠適用於各類類型的客戶端(好比服務端應用,移動APP,JS應用),且徹底兼容OAuth2,也就是說你搭建了一個OIDC的服務後,也能夠看成一個OAuth2的服務來用。應用場景如圖:github
OIDC已經有不少的企業在使用,好比Google的帳號認證受權體系,Microsoft的帳號體系也部署了OIDC,固然這些企業有的也是OIDC背後的推進者。除了這些以外,有不少各個語言版本的開源服務端組件,客戶端組件等等(http://openid.net/developers/certified/);web
理解OIDC的前提是須要理解OAuth2,這裏假設你們都有OAuth2的基礎,不清楚的能夠先閱讀本系列的前幾篇OAuth2的文章。json
OIDC自己是有多個規範構成,其中包含一個核心的規範,多個可選支持的規範來提供擴展支持,簡單的來看一下:後端
除了上面這8個以外,還有其餘的正在制定中的擴展。看起來是挺多的,不要被嚇到,其實並非很複雜,除了Core核心規範內容多一點以外,另外7個都是很簡單且簡短的規範,另外Core是基於OAuth2的,也就是說其中不少東西在複用OAuth2,因此說你理解了OAuth2以後,OIDC就是很是容易理解的了,咱們這裏就只關注OIDC引入了哪些新的東西(Core,其他7個可選規範不作介紹,可是可能會說起到)。千言萬語都不如一張圖,沒圖你說個***。安全
上圖是官方給出的一個OIDC組成結構圖,咱們暫時只關注Core的部分,其餘的部分了解是什麼東西就能夠了,看成黑盒來用。就像當初的AJAX同樣,它其實並非一個新的技術,而是結合不少已有的技術,按照規範的方式組合起來,就是AJAX。同理,OIDC也不是新技術,它主要是借鑑OpenId的身份標識,OAuth2的受權和JWT包裝數據的方式,把這些技術融合在一塊兒就是OIDC。服務器
OAuth2提供了Access Token來解決受權第三方客戶端訪問受保護資源的問題;OIDC在這個基礎上提供了ID Token來解決第三方客戶端標識用戶身份認證的問題。OIDC的核心在於在OAuth2的受權流程中,一併提供用戶的身份認證信息(ID Token)給到第三方客戶端,ID Token使用JWT格式來包裝,得益於JWT(JSON Web Token)的自包含性,緊湊性以及防篡改機制,使得ID Token能夠安全的傳遞給第三方客戶端程序而且容易被驗證。此外還提供了UserInfo的接口,用戶獲取用戶的更完整的信息。session
主要的術語以及概念介紹(完整術語參見http://openid.net/specs/openid-connect-core-1_0.html#Terminology):
從抽象的角度來看,OIDC的流程由如下5個步驟構成:
上圖取自Core規範文檔,其中AuthN=Authentication,表示認證;AuthZ=Authorization,表明受權。注意這裏面RP發往OP的請求,是屬於Authentication類型的請求,雖然在OIDC中是複用OAuth2的Authorization請求通道,可是用途是不同的,且OIDC的AuthN請求中scope參數必需要有一個值爲的openid的參數(後面會詳細介紹AuthN請求所需的參數),用來區分這是一個OIDC的Authentication請求,而不是OAuth2的Authorization請求。
上面提到過OIDC對OAuth2最主要的擴展就是提供了ID Token。ID Token是一個安全令牌,是一個受權服務器提供的包含用戶信息(由一組Cliams構成以及其餘輔助的Cliams)的JWT格式的數據結構。ID Token的主要構成部分以下(使用OAuth2流程的OIDC)。
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 }
解釋完了ID Token是什麼,下面就看一下OIDC如何獲取到ID Token,由於OIDC基於OAuth2,因此OIDC的認證流程主要是由OAuth2的幾種受權流程延伸而來的,有如下3種:
這裏有個小問題你們能夠思考下,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來作身份認證的事情是遠遠不夠的,也是不合適的。
這種方式使用OAuth2的Authorization Code的方式來完成用戶身份認證,全部的Token都是經過Token EndPoint(OAuth2中定義:https://tools.ietf.org/html/rfc6749#section-3.2)來發放的。構建一個OIDC的Authentication Request須要提供以下的參數:
以上這5個參數是和OAuth2相同的。除此以外,還定義了以下的參數:
以上是基於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的重定向方式。
在受權服務器接收到認證請求以後,須要對請求參數作嚴格的驗證,具體的規則參見http://openid.net/specs/openid-connect-core-1_0.html#AuthRequestValidation,驗證經過後引導EU進行身份認證而且贊成受權。在這一切都完成後,會重定向到RP指定的回調地址,而且把code和state參數傳遞過去。好比:
HTTP/1.1 302 Found Location: https://client.example.org/cb? code=SplxlOBeZQQYbYS6WxSbIA &state=af0ifjsldkj
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" }
其中看起來一堆亂碼的部分就是JWT格式的ID Token。在RP拿到這些信息以後,須要對id_token以及access_token進行驗證(具體的規則參見http://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation和http://openid.net/specs/openid-connect-core-1_0.html#ImplicitTokenValidation)。至此,能夠說用戶身份認證就能夠完成了,後續能夠根據UserInfo EndPoint獲取更完整的信息。
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,也再也不詳細介紹了。
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": "janedoe@example.com", "picture": "http://example.com/janedoe/me.jpg" }
其中sub表明EU的惟一標識,這個claim是必須的,其餘的都是可選的。
繼OAuth2以後,感受OIDC也要大放異彩了。其自己是一個徹底開放的標準,並且兼容衆多的已有的IDP(身份提供商),好比基於SAML的、基於WS-Federation的等等已有的身份認證系統,均可以做爲OIDC的OP存在。總結一下OIDC有那些特性和好處吧:
以上內容均是我的的一些理解,若是錯誤之處,歡迎指正!
筆者基於IdentityServer3和IdentitySever4(二者都是基於OIDC的一個.NET版本的開源實現)寫的一個集成SSO,API訪問受權控制,QQ聯合登錄(做爲OP)的demo:https://github.com/linianhui/oidc.example 。
官方資料:
http://openid.net/connect/faq/
http://openid.net/developers/certified/
JWT : https://tools.ietf.org/html/rfc7519
JWS:https://tools.ietf.org/html/rfc7515
JWE:https://tools.ietf.org/html/rfc7516
.NET的開源實現:https://github.com/IdentityServer
視頻:Identity, Authentication + OAuth = OpenID Connect
案例:
https://developers.google.com/identity/protocols/OpenIDConnect