当互联网应用越来越多,每个应用程序都实现了自己的身份存储、认证和授权,用户需要在应用上反复的注册与登录,体验糟糕,用户身份信息无法在多个应用间共享与同步。当使用企业应用时,企业提供了一系列应用,尽管是同一用户操作,但还是不得不切换注册与登录。
是否可以有那么一种方式,我在某个代理网站注册一个账号,如果登录其他网站时,其他网站可以到代理网站去获取信息。只要代理网站足够富有生命力,那么总是可以省略很多乏味的注册登录流程。
这些想法在技术的发展过程中出现了,如WS-Federation、SAML2.0、OpenID、OAuth、OIDC...
还有一些修订和扩展,此处就不体现了,主要是想聚焦于OpenID和OAuth是不一样的。
OpenID是一个去中心化的网上身份认证系统。对于支持OpenID的网站,用户不需要记住像用户名和密码这样的传统认证标记。取而代之的是,他们只需要预先在一个作为OpenID身份提供者(identity provider, IdP)的网站上注册。OpenID是去中心化的,任何网站都可以使用OpenID来作为用户登录的一种方式,任何网站也都可以作为OpenID身份提供者。OpenID既解决了注册问题而又不需要依赖于中心性的网站来确认数字身份。
OpenID给用户提供一个统一网络身份,遵守OpenID网络身份,遵守OpenID协议的应用网站(在OpenId术语里叫Relying Parties,即RP)需要用户登录时,引导用户到第三方OpenID身份提供方(OpenId术语里叫OpenID identity provider,即OP)去认证,认证通过即登录成功。这样就省去了每个应用网站注册、登录的烦恼与乏味。解决了最开始提到的一个问题,各应用需要独立完成注册与登录流程,需要实现与维护独立的用户数据库。
OAuth是一个授权协议,解决的是应用可以访问用户在另一应用上的某些授权资源,但此应用不需要知道用户在另一应用上的账户密码,即无需向另一应用透露用户的凭据便可以访问另一应用上受控的资源。
OpenID团队本来希望用户使用OpenID来进行身份认证, 但因为授权过程包括认证过程作为一部分,所以授权意味着经过了认证这一过程。由此,一些用户选择了OAuth身份认证的简易性,并且由于“管理用户凭据的任务可以委托给外部服务”以及“因为新用户注册过程可以省略,使用该服务的障碍变得更低”等优点而迅速占据主导地位,使用OAuth2.0作为身份认证的趋势变得流行。
OpenID团队不得不承认用户更喜欢OAuth2.0,因此,他们在OAuth之上定义了一个新的身份认证规范OpenIDConnect(OIDC),这个规范基于OAuth2.0进行了小幅扩展,在OAuth2.0上构建了身份层,使其可用作身份认证协议。
即OpenID Connect (OIDC) 是基于 OAuth 2.0 构建的身份认证协议。
OpenID+OAuth 2.0=OpenID Connect
OIDC由一系列规范文档组成,包括一个核心文档和多个可选支持的文档来提供扩展支持:
对于这些协议来讲,可能看着就难受,简要了解个概念即可,实际开发时这些都会逐渐浮出水面。
OIDC仍然使用OAuth中的授权服务器将用户身份认证信息以Id token的方式给到第三方应用,第三方应用可以验证用户标识并从中获取用户的基本信息以及通过OAuth2.0的授权流程访问用户的详细信息。如下图所示,对于用户认证部分采用认证协议如WS-Fed、OIDC等,对于资源的访问控制以OAuth2.0协议为主。
OIDC中的Id token和OAuth2.0中核心的Access token各自效力或是关注的部分不同。
Access Token
来解决授权第三方应用访问受保护资源的问题;ID Token
来解决第三方应用标识用户身份的问题。OIDC的流程主要由以下5个步骤构成:
流程上,在OAuth2.0中授权码模式和隐式授权模式下,OIDC和OAuth2.0是一样的,但有几个授权模式在某些情况下,在OIDC中就不存在了,当用户无需经过身份认证过程即可获得Access token,比如如下两种模式。
OIDC的认证流程主要是由OAuth2的几种授权流程延伸而来的,主要有以下3种:
1、第三方应用通过浏览器重定向到授权服务器(OP)的认证页面来进行用户认证与执行授权流程。重定向时使用的参数是基于OAuth2.0中的大部分参数。主要如下几个
2、当用户完成认证信息填写与执行授权操作后,授权服务器(OP)对用户认证信息的审核和授权范围的校验。有效后重定向到第三方应用(RP)指定的回调地址(第1步中的redirect_uri),将code和state参数作为查询参数附加在回调地址后。
3、第三方应用(RP)通过code来请求认证服务方的Token EndPoint换取Token。
然后Token EndPoint会返回响应的Token,其中除了OAuth2规定的部分数据外,还会附加一个id_token的字段。
{ "access_token": "SlAV32hkKG", "token_type": "Bearer", "refresh_token": "8xLOxBtZp8", "expires_in": 3600, "id_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" }
4、请求用户信息或授权内的资源。
在OAuth2.0中,隐式授权使用的response_type是token,而在OIDC中,变为了id_token token或是仅id_token,当仅使用id_token时,则不会返回Access token了。其余参数则和OAuth2.0中的隐式授权一致。但OIDC中相比OAuth2.0隐式流程额外增加了一个参数nonce
注意:隐式流程中OAuth2.0的state和OIDC的nonce区别
1、第三方应用(RP)携带参数跳转到授权服务器(OP)的认证授权页面,等待用户认证与执行授权。
2、当授权服务器(OP)完成对用户认证信息的审核和授权范围的校验,重定向回第三方应用(RP)并按照请求时的response_type返回id token、access token(当仅设置id_token时不返回)。注意url的hash部分(#后面)。
3、后续便是请求用户信息或是授权内的资源。
这种是将授权码和隐式流程结合起来,一部分token来源于授权服务器(OP)重定向到第三方应用(RP)时带过来,一部分来源于第三方应用(RP)向授权服务器(OP)发起请求而得到。这种流程中,response_type,可以混合着用,如code id_token,code token或是code id_token token。
1、第三方应用(RP)向授权服务器(OP)发起认证请求。此处使用授权码和隐式中仅id_token的组合。
2、当授权服务器(OP)完成对用户认证信息的审核和授权范围的校验,重定向回第三方应用(RP)并按照请求时的response_type返回id token、access token(当仅设置id_token时不返回)。
3、第三方应用(RP)通过code来请求授权服务器(OP)换取Token。这和授权码流程一致了。
认证服务返回的ID Token需要严格遵守JWT(JSON Web Token)的定义,下面是JWT(JSON Web Token)的定义细节:
{ "exp": 1614187991, "iss": "https://authorization-server.com/oauth", "sub": "a0903223-a120-91e0-c342-10bd237c24c1", "aud": "client1", "iat": 1614151991, "auth_time": 0, "nonce": "n-0S6_WzA2Mj", "acr": "1", "azp": "client1", "nbf": 0, "typ": "ID", "session_state": "150df80e-92a1-4b0c-a5c5-8c858eb5a848", "userId": "123456", "preferred_username": "testera", "given_name": "tester", "family_name": "a", "email": "testera@myweb.com" }
关于ID Token的更详细的定义请参见OpenID Connect Core 1.0。
https://www.jianshu.com/p/2c602974bc98
https://baike.baidu.com/item/OpenID?wtp=tt
http://www.imooc.com/article/4167
https://www.cnblogs.com/linianhui/p/openid-connect-core.html