OAuth2.0 提供了一个框架,主要是为了应用程序调用 API 的授权而设计,但不是为验证用户而设计的。
因为互联网的应用越来越多,不同的应用之间需要共享身份,亟需一个大家公认的标准来进行身份的共享。同时,因为技术的演进(微服务、云原生),对于 API 的授权需求越来越多。OAuth2.0 的一些实现为此添加了专有的验证身份附加内容,一个标准的解决方案 OpenID Connect( OIDC)。
什么是 OIDC
OpenID Connect(OIDC)i 协议在 Oauth2.0 之上提供了一个身份服务层,旨在允许授权服务器对应用程序的用户进行身份验证,并以标准的方式返回结果。
在 OIDC 在 Oauth2.0 的基础之上提供了 id token 以传递用户的身份信息。而且,在 OIDC 标准中还升级扩展了更多的 scopes 和 claims。
尽管 OIDC 建立在 OAuth2.0 的基础之上,但 OIDC 中对几个角色的描述略有不同:
-
OpenID Provider(OP):OP 是 OIDC 协议中的授权服务器实,用于验证用户身份、签发 access token 、id token 和 refresh token(通常会是 IDaaS 的一个基本的服务)。
-
**End User **:最终用户是要验证的主体。 (即通俗理解为 PC 或者手机屏幕前的用户,一个现实存在人。)
-
relaying Provider(RP):向 XAuth 授权服务请求 access token 和 id token 的应用(通常指第三方或者开发者开发的应用)。
-
id token:id token是由 OP 签发的,在 id token 中通过一组 claims 描述用户的身份信息(用于描述人的身份信息的一些属性的集合)。
-
claim:每一条 claim 对应着用户的一个属性信息。
如果期望快速的学习 Ouath2.0 协议的流程,请查看 XAuth 的电子书《现代身份管理指南》的第七章——深入学习 OIDC
术语解释
公共与非公开的客户端
OIDC 定义了客户端的类型与 OAuth2.0 定义的两种客户端类型类似:
- 公共客户端 – 一种主要在用户侧设备上运营的程序,如(手机 APP 应用程序)或客户端浏览器中执行的应用程序,它不能安全地存储秘密。OAuth2.0 本机应用程序定义了最佳的实践。ii
- 非公开客户端 – 在受保护的服务器上运行的一种应用程序,它可以安全地存储机密,可以一种安全的机制向授权服务器进行身份验证,并存储授权服务器返回的机密。
令牌和授权码
OIDC 使用授权码、访问令牌和刷新令牌,如 OAuth2.0 所述,并定义一个 ID 令牌。
- 授权码 – 返回给应用程序的一种中间的不透明一次性代码,用于获取访问令牌和可选的刷新令牌。每个授权码使用一次。
- 访问令牌:应用程序用来访问 API 的令牌。 它表示应用程序调用 API 的授权,并且有一个过期时间
- 刷新令牌:一种可选令牌,当先前的访问令牌过期时,应用程序可以使用它来请求新的访问令牌。
- ID 令牌:一种令牌,用于向依赖方(应用程序)传递有关认证事件和用户的声明。
端点
OIDC 除了利用 OAuth 2.0 中描述的的授权和令牌端点以外,增加加 UserInfo 端点。
UserInfo Endpoint–返回关于经过身份验证的用户的声明。调用端点需要访问令牌,并且返回的声明由访问令牌控制。
ID Token
ID Token 令牌是 OpenID 提供者用来向应用程序传递关于身份验证事件和身份验证用户的声明的安全令牌。ID 令牌以 Json Web Token(JWT)格式编码。
JWT 格式旨在在双方之间传递声明。作为 JWT,ID 令牌由报头(Header)、有效负载(Payload)和签名(Signature)组成。最终,这些组合在一起通过 base-64 进行编码。
-
ID 令牌的头部分
包含关于对象类型(JWT)和用于保护有效负载中声明的完整性的特定签名算法的信息。常见的签名算法有 HS256(HMAC 带 SHA256)或 RS256(RSA 带 SHA256 签名)。
-
有效负载(Payload)部分
包含关于用户和身份验证事件的声明。主要包括:
-
发行人
-
主体或经过身份验证的用户(通常是资源所有者)
-
用户如何认证以及何时认证
-
令牌的对象(即受众)
这些标记非常灵活,允许您添加自己的声明
-
-
签名部分
包含基于 ID 令牌的有效负载部分的数字签名和 OpenID 提供者已知的密钥。
OpenID 提供者根据签名规范(JWS)iv对 JWT 进行签名。RP 应用程序可以验证 ID 令牌上的签名,以检查其中声明的完整性。为了保密,OpenID 提供者可以选择在 JWT 签名后使用 Jsonweb 加密(JWE)v对其进行加密。如果这样做,它将生成一个嵌套的 JWT。
OIDC 如何工作
与 OAuth2.0 中定义的授权流程类似,OIDC 流程围绕不同应用程序的类型而设计的,OIDC 核心规范定义了以下流程:
- 授权码流程
- 隐式流程
- 混合流程
以下各节将介绍每种方法的工作原理:
OIDC 授权码模式
OIDC 授权代码流类似于 OAuth2.0 授权代码授,整个流程中,主要依赖于两次请求和一个中间授权代码。为了验证用户身份,应用程序将用户的浏览器重定向到 OpenID 提供者。OpenID 提供者对用户进行身份验证,并使用授权码将用户的浏览器重定向回应用程序。应用程序使用授权代码从 OpenID 提供者的令牌端点获取 ID 令牌、访问令牌和可选的刷新令牌。图 7-3 描述了这个流程,假设用户当前没有登录会话,应用程序最终请求了全部的三个安全令牌(IDToken、AccessToken、Refresh Token)
- 用户向应用(RP)发起请求
- 应用向 OpenID 提供者发出一个请求,发送一个基本的授权范围,该请求通过浏览器进行重定向。
- OpenID 提供者接下来将向用户发起身份验证,和征求用户的授权同意。
- 用户通过输入凭据进行身份验证,并且对请求的权限进行授权,该授权将影响令牌中包含影响作用域的信息。
- OpenID 提供者生成本次授权请求的授权码,然后将此授权码包含在重定向请求中,通过浏览器将授权码返回给应用。
- 应用向 OpenID 提供者的令牌端点发送获取令牌请求,在此请求中,包含了授权码,以获取访问令牌。
- OpenID 提供者向该应用颁发访问令牌(AccessToken)、ID 令牌和刷新令牌(可选)。
- 应用使用此访问令牌来调用 OpenID 提供者的用户信息的 API。
注意:
步骤 6 调用令牌端点以获取安全令牌时,如果应用程序是非公开客户端,能够向 OpenID 提供程序进行自己的身份验证,则不需要 PKCE 的模式。如果,应用是不能安全地维护此类身份验证的秘密的公共客户端应用程序,可以使用密码交换证明密钥(PKCE)。PKCE 的使用旨在降低授权代码被未授权方截获的风险。
OIDC 隐式模式
实践中不建议使用 OAuth2.0 隐式授权来获取访问令牌,至少在默认响应模式下是这样。该指导原则的前提是基于 URL 片段中的访问令牌可能存在暴露的风险,即该 URL 片段可能通过浏览器历史记录或 referer 头泄漏。如果,应用程序只需要对用户进行身份验证并且可以通过 ID 令牌获取用户信息,而不需要访问令牌。在这种情况下,隐式流是可以接受的。
- 用户向应用(RP)发起请求
- 应用向 OpenID 提供者发出一个请求,发送一个基本的授权范围,该请求通过浏览器进行重定向。
- OpenID 提供者器接下来将向用户发起身份验证,和征求用户的授权同意范围。
- 用户通过输入凭据进行身份验证,并且对请求的权限进行授权,该授权将影响令牌中包含影响作用域的信息。
- OpenID 提供者生成本次授权请求的身份令牌(IDToken),然后将此令牌包含在重定向请求中,通过浏览器将令牌返回给应用。
- 应用程序从 ID 令牌获取关于用户身份的声明,并向用户显示需要展示的内容。
OIDC 混合流程
OIDC 混合流包含授权代码流和隐式流程的元素。它是为既有安全后端,又有在前端执行 JavaScript 的客户端的应用程序而设计的。混合流支持诸如在对应用程序前端的前通道响应中返回 ID 令牌和授权码、让应用程序后端使用授权码从令牌端点获取访问令牌(和可选的刷新令牌)之类的模型。该流程如图所示。
- 用户向应用(RP)发起请求
- 应用向 OpenID 提供者发出一个请求,发送一个基本的授权范围,该请求通过浏览器进行重定向。
- OpenID 提供者接下来将向用户发起身份验证,和征求用户的授权同意。
- 用户通过输入凭据进行身份验证,并且对请求的权限进行授权,该授权将影响令牌中包含影响作用域的信息。
- OpenID 提供者生成本次授权请求的授权码和 IDToken,然后将此授权码和 IDToken 包含在重定向请求中,通过浏览器将授权码和 ID Token 返回给应用。
- 客户端验证 ID Token,如果合法,应用后端使用授权码向 OpenID 提供者的令牌端点发送获取令牌请求,以获取访问令牌。
- 授权服务器向该应用颁发授权令牌(AccessToken),刷新令牌(可选)。
- 应用使用此令牌来访问用户信息。