看一下官方的介绍(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