OAuth 2.0 与 OIDC
1 OAuth 2.0
OAuth 2.0 是一个标准的 Authz 协议(没有 Authn 功能)。如果期望将 Resource 授权给第三方应用,那么就可以使用 OAuth 2.0。
OAuth 2.0 协议中主要有四个角色:
- Resource Owner - 能够授权 Client 访问资源的角色。最典型的就是 User。
- Resource Server - 存放 Resource 的服务器,能够验证 Access Token 来决定是否返回 Resource
- Authz Sever - 对 Resource Owner 进行认证,并负责颁发 Access Token。
- Client - 第三方应用,得到 Resource Owner 授权后,请求访问 Resource
其他一些重要概念:
- Grant - Resource Owner 授予 Client 凭证,用它来访问 Authz Server
- Access Token - 由 Authz Server 颁发的 Token,通过 Token 来访问 Resource Server
- Refresh Token(可选)- 用于 Access Token 过期后获取一个新的 Access Token。
可以看到,Authz Server 集中了鉴权的功能。通过给 Client 颁发 Token,使得 Client 在不知道账户密码的情况下,能够访问 Resource Server 获取资源。
2 OIDC
OIDC 是基于 OAuth 2.0 的 Authn 协议,增加了 ID Token 的概念。OIDC 也指定了 OAuth 2.0 中未定义的部分,包括:scope、服务发现、用户信息字段等。
OIDC 中的角色如下:
- End User - 终端用户,对应于 OAuth 2.0 中的 Resource Owner,ID Token 中会包含 End User 相关的信息
- Relying Party - 第三方应用,对应于 OAuth 2.0 中的 Client
- OpenID Provider - Auth Server,负责签发 ID Token 与 Access Token
- Resource Server
其他一些重要概念:
- ID Token - 由 OpenID Provider 颁发的 Token,包含了 EU 的身份信息
- Claim - ID Token 中 EU 信息相关的字段
- UserInfo Endpoint - OpenID Provider 提供的获取 EU 更多信息的接口
OIDC 提供的 Authz 流程与 OAuth 2.0 一样,主要区别在于 OIDC 在 Authz 过程中会额外返回 ID Token。
3 Authz 流程
3.1 基本流程
最基本的访问流程如下:
- App 请求 Resource Owner,获取 Grant。
- App 携带 Grant 访问 Authz Server,获取 Access Token 与 ID Token。
- App 携带 Token 访问 Resource Server,获取 Resource。
基于三个步骤扩展出来,OAuth 2.0 提出了四种授权方式。
3.2 Authz Code 授权码模式
Authz Code 是最严格但最常见的方式,考虑了几乎所有的敏感信息泄漏的预防和后果。对于基本流程的第 1 步以及第 2 步都有了扩展。
- App 往往是一个后端服务,必须提供回调 URL(预先提供给 Authz Server)。通过访问 URL 能够将 Authz Code 传递给 App,然后 App 自己存储 Authz Code。
- Resource Owner 需要手动登陆 Authz Server 的登录页面。
-
获取 Grant(Authz Code)
- App 发起授权请求
- Authz Server 将请求重定向到授权页面
- Resource Owner 手动登陆 Authz Server 的授权页面,表示允许 Grant。
- Authz Server 返回的 URL 和 Authz Code,浏览器通过重定向访问 URL,也就是访问后端服务,将 Authz Code 传输给 App。
-
获取 Access Token
-
Client 拿到 Authz Code 后,就能够使用 Authz Code 访问 Authz Server,这样来申请 Access Token 与 ID Token。
如果需要,还会返回 Refresh Token。
-
-
通过 Token 访问 Resource Server
3.3 Implicit 隐式授权模式
Implicit 省略了 Authz Server 颁发 Authz Code 的步骤,并且明确禁止发放 Refresh Token。该模式适用于 App 无法存储 Authz Code 的情况。
App 发起请求时,会指定接收 Token 的 URL。完成 Grant 后,Authz Server 会回调 URL 来提供 Token。
3.4 Resource Owner Password Credentials 密码模式
Resource Owner Password Credentials 整合了 Authn 与 Authz 的过程。Resource Owner 直接提供账号密码给 App,App 使用账号密码去 Authz Server 获取 Token。
因为 Client 直接拿着密码,所以这种模式适用于 Client 高度可信的情况下。
3.5 Client Credentials 客户端模式
Client Credentials 指的是:App 直接使用 Resource Owner 提供的 Credentials,向 Authz Server 申请 Token。
该模式常用于 CICD 与服务间的认证授权(M2M 授权)。
3.6 Hybrid 混合模式
完成 Grant 后,Auth Server 同时返回 Token 与 Authz Code。App 可以直接使用 Token,后续可以使用 Authz Code 重新获取 Token。
4 Token
4.1 Access Token
通常 Access Token 是 JWT Base64 编码。其中包含了常见的鉴权使用的字段:
|
|
4.2 ID Token
OIDC 对 OAuth 2.0 最主要的扩展就是 ID Token。ID Token 相当于用户的身份凭证。应用可以通过校验 ID Token 以确定用户身份。
ID Token 本质上是 JWT Token
,包含用户信息的 K/V 键值对。
|
|
可以看到,ID Token 通过 JWT Token 直接承载了用户信息。但是因为 JWT Token 无法承载太多信息,因此协议定义了 UserInfo Endpoint 接口来用于获取更多的用户信息。
当 RP 收到 OP 提供的 ID Token 与 Access Token 后,可以调用 UserInfo Endpoint 获取更多用户信息。
4.3 Refresh Token
Access Token 以及 ID Token 的有效期比较短。失效后,Client 需要重新获取 Grant,然后重新去 Authz Server 获取一个新的 Access Token。
为了让 Client 跳过获取 Grant 的流程,Authz Server 提供 Access Token 同时也会提供 Refresh Token。
Client 携带 Refresh Token 能够重新从 Authz Server 获取一个 Access Token,而不需要再次获取 Grant。
4.4 如何验证 Token
当 Resource Server 收到 Access/ID Token,通过 JWT 的 Signature
信息来验证 Token 是否合法。
- 例如使用 RS256 算法(非对称加密),Auth Server 会使用 Private Key 对
Header
与Payload
进行加密。应用收到 Token 后就可以使用 Public Key 来解密验证Signature
。 - 例如使用 HS256 算法(对称加密),Auth Server 会使用 Secret 对
Header
与Payload
进行加密。应用需要先从 Auth Server 获取 Secret,然后收到 Token 后解密来验证(或者调用 Auth Server 接口验证)。
4.5 传递 Token
RFC 6750 定义了 Client 如何将 Access Token 传递给 Resource Server。
-
URI Query Parameter - 基于 Param 传递
1 2
GET /resource?access_token=mF_9.B5f-4.1JqM HTTP/1.1 Host: server.example.com
注意添加
Cache-Control:no-store
防止中间件缓存。 -
HTTP Header - 基于 HTTP Header
Authorization
1 2 3
GET /resource HTTP/1.1 Host: server.example.com Authorization: Bearer mF_9.B5f-4.1JqM
最常见的方式,其中
Bearer
是固定的前缀。 -
HTTP Body - 基于 HTTP Body
1 2 3 4 5
POST /resource HTTP/1.1 Host: server.example.com Content-Type: application/x-www-form-urlencoded access_token=mF_9.B5f-4.1JqM
不允许使用
Get
方式,并且必须设置Content-Type: application/x-www-form-urlencoded
。
5 Federation Auth
Auth 流程中描述的都是 Authz Server 负责了 Authn 功能,来颁发 ID Token。一些场景下,可能 App 想复用互联网产品的账号来进行身份认证,例如网站支持使用 QQ 登陆。这种情况下,可以使用 Federation Auth。
通常,Identity Provider 分为三类:
- Social Identity Provider - Identity Provider 为第三方社交平台,例如微信、QQ、Google 等;
- Enterprise Identity Provider - Identity Provider 为办公应用(例如飞书、企业微信)或标准协议应用(例如 OIDC、SAML、CAS 等标准协议);
- Database Identity Provider - 提供给 Authz Server 一个数据库,用于存放身份信息;