-
开发者谈 | OAuth 2.0 和 OIDC 协议的关系?(内含必看案例)
-
【Web 安全】CSRF 攻击详解
OAuth 2.0
- OAuth 2.0 的一个简单解释
- OAuth 2.0 的四种方式
- 什么是Oauth2.0,Oauth2.0的四种授权模式
简单说,OAuth 就是一种授权机制。数据的所有者告诉系统,同意授权第三方应用进入系统,获取这些数据。系统从而产生一个短期的进入令牌(token),用来代替密码,供第三方应用使用。
OAuth 的核心就是向第三方应用颁发令牌
令牌与密码
令牌(token)与密码(password)的作用是一样的,都可以进入系统,但是有三点差异。
(1)令牌是短期的,到期会自动失效,用户自己无法修改。密码一般长期有效,用户不修改,就不会发生变化。
(2)令牌可以被数据所有者撤销,会立即失效。以上例而言,屋主可以随时取消快递员的令牌。密码一般不允许被他人撤销。
(3)令牌有权限范围(scope),比如只能进小区的二号门。对于网络服务来说,只读令牌就比读写令牌更安全。密码一般是完整权限。
上面这些设计,保证了令牌既可以让第三方应用获得权限,同时又随时可控,不会危及系统安全。这就是 OAuth 2.0 的优点。
注意,只要知道了令牌,就能进入系统。系统一般不会再次确认身份,所以令牌必须保密,泄漏令牌与泄漏密码的后果是一样的。 这也是为什么令牌的有效期,一般都设置得很短的原因。
OAuth 2.0
OAuth 即 Open Authorization ,开放授权。
OAuth 2.0 是一个授权标准协议,可以使第三方应用获得对资源服务的有限访问。
根据 OAuth 2.0 协议规范,定义了四个角色:
资源所有者(Resource Owner):能够授予对受保护资源访问权限的实体。例如应用的用户是资源的所有者,可以授权其他人访问他的资源。当资源所有者是一个人时,它被称为最终用户。 —— 就相当于 admin,控制授予 Access Token 何种权限
资源服务器(Resource Server):存储受保护资源的服务器,能够接受并使用访问令牌来响应受保护的资源请求。就是资源服务器接受 Access Token,然后验证它拥有的权限,最后返回对应的资源。这个资源服务器一般是应用本身。—— 验证 Access Token 和相应的权限,并返回资源
授权服务器(Authorisation Server):服务器向客户端(即应用)颁发访问令牌来验证资源所有者并获得授权。即负责颁发 Access Token 的服务器,例如 IDaaS 就是一个授权服务器。—— 向客户端发放 Access Token
客户端(Client):需要获取访问令牌以访问资源服务器的应用。经过授权后,授权服务器为客户端颁发 Access Token。后续客户端可以携带这个 Access Token 到资源服务器那访问用户的资源。—— 需要 Access Token 来获取资源
在 OAuth 2.0 中一个应用可能既是 Resource Server,也是 Client,具体是什么角色,取决于应用工作的场景。
概念可能有点难嚼,还请慢咽。
这四个角色一直在围绕着一个叫 Access Token 的东西在转圈圈。
Access Token 也就是访问令牌,它用于允许应用访问一个资源 API。用户认证授权成功后,授权服务器会签发 Access Token 给应用。应用后续需要携带 Access Token 访问资源 API,资源服务 API 会检验 Access Token 是否有权限访问,从而决定是否返回对应资源。
而 Access Token 本质上只是一串随机字符串,并不能从中获取到任何信息,检验 Access Token 的步骤还需要资源服务器将它转发到授权服务器上进行解析验证。
了解完 Access Token 之后,我们来关注一下客户端调用方是如何获取到它的,也就是授权模式的选择。
授权码模式(Authorization Code):适用于具有完整前后端的传统 Web 应用以及移动或桌面端应用。
隐式模式(Implicit):适用于没有后端的基于浏览器(JavaScript)的纯前端应用。
密码模式(Resource Owner Password Credentials):适用于资源服务器和客户端之间高度信任的情况下,例如自家应用使用自家的资源。
客户端凭证模式(Client Credentials):适用于没有前端参与,纯后端交互的情况,期间没有用户的参与,客户端自己就是资源所有者。
…我们重点关注授权码模式和客户端凭证模式,这两个是最常用的。
流程
OAuth2.0协议流程描述了四种角色之间的交互过程,如下图所示。
上面的序列图一共分为以下6个步骤:
(1)第三方应用请求资源所有者授权。
(2)资源所有者同意给第三方应用授权。
(3)第三方应用使用步骤2中获得的授权,向授权服务器申请令牌。
(4)授权服务器对第三方应用进行认证并确认无误后,同意发放令牌。
(5)第三方应用使用步骤4中发放的令牌向资源服务器申请获取资源。
(6)资源服务器确认令牌无误后,向第三方应用开放资源访问。
四种模式
OAuth 2.0 对于如何颁发令牌的细节,规定得非常详细。具体来说,一共分成四种授权类型(authorization grant),即四种颁发令牌的方式,适用于不同的互联网场景。
1. 隐式授权模式(Implicit Grant)
- 第一步:用户访问页面时,重定向到认证服务器。
- 第二步:认证服务器给用户一个认证页面,等待用户授权。
- 第三步:用户授权,认证服务器想应用页面返回Token
- 第四步:验证Token,访问真正的资源页面
2. 授权码授权模式(Authorization code Grant)
示例见 开发者谈 | OAuth 2.0 和 OIDC 协议的关系?(内含必看案例)
- 第一步:用户访问页面
- 第二步:访问的页面将请求重定向到认证服务器
- 第三步:认证服务器向用户展示授权页面,等待用户授权
- 第四步:用户授权,认证服务器生成一个code和带上client_id发送给应用服务器
然后,应用服务器拿到code,并用client_id去后台查询对应的client_secret - 第五步:将code、client_id、client_secret传给认证服务器换取access_token和
refresh_token - 第六步:将access_token和refresh_token传给应用服务器
- 第七步:验证token,访问真正的资源页面
3. 密码模式(Resource Owner Password Credentials Grant)
- 第一步:用户访问用页面时,输入第三方认证所需要的信息(QQ/微信账号密码)
- 第二步:应用页面那种这个信息去认证服务器授权
- 第三步:认证服务器授权通过,拿到token,访问真正的资源页面
优点:不需要多次请求转发,额外开销,同时可以获取更多的用户信息。(都拿到账号密码了)
缺点:局限性,认证服务器和应用方必须有超高的信赖。(比如亲兄弟?)
应用场景:自家公司搭建的认证服务器
4. 客户端凭证模式(Client Credentials Grant)
- 第一步:用户访问应用客户端
- 第二步:通过客户端定义的验证方法,拿到token,无需授权
- 第三步:访问资源服务器A
- 第四步:拿到一次token就可以畅通无阻的访问其他的资源页面。
这是一种最简单的模式,只要client请求,我们就将AccessToken发送给它。这种模式是最方便但最不安全的模式。因此这就要求我们对client完全的信任,而client本身也是安全的。
因此这种模式一般用来提供给我们完全信任的服务器端服务。在这个过程中不需要用户的参与。
OpenID Connect
讲完 OAuth 2.0 授权,来到 OIDC 认证协议。
如标题,OIDC 全称是 OpenID Connect,是一个基于 OAuth 2.0 的认证 + 授权(OAuth 2.0 提供的能力)协议。
OIDC 可以理解为 OAuth 2.0 的超集,在 OAuth 2.0 之上实现了更多的标准,例如定义了一系列的 EndPoint 。还有一些规范诸如 Session Management,Front-Channel Logout,Back-Channel Logout 等。
OIDC 之所以有认证的功能,是因为在 OAuth 2.0 颁发 Access Token 的基础上,多颁发了一个 ID Token(用户的身份凭证),和 Access Token 是一个随机字符串不同的是,ID Token 是一个 JWT Token 。
ID Token 自身包含了一些用户的基本信息,而且由于 JWT 的防篡改性,让客户端不需要再向授权服务器进行身份验证,就能直接用 ID Token 来进行身份验证。即使 ID Token 包含的用户信息不够,也可以调用 OIDC 定义的 UserInfo EndPoint(用户信息接口)来获取更多的用户信息。
OIDC 协议定义的名词和 OAuth 2.0 协议定义的稍微有些出入:
-
OpenID Provider ,简称 OP :相当于 OAuth 2.0 中的授权服务器,除了负责颁发 Access Token ,还会颁发 ID Token 。例如 IDaaS 就是一个 OP 。
-
Relying Party ,简称 RP :代指 OAuth 2.0 中的客户端。
-
End User ,简称 EU :即用户。
最后, OIDC 的授权流程与 OAuth 2.0 是一样的,主要区别在于 OIDC 授权流程中会额外返回 ID Token。
云原生下的 OIDC Provider 服务
IDaaS 的认证和授权使用了 OIDC/OAuth 2.0。说白了,要搭建 IDaaS 得先搭建一个授权服务器 OpenID Provider (更多时候称之为 OIDC Provider )。
但即便完全了解 OIDC 协议,自行实现一套完整的 OIDC Provider 依旧十分繁琐,好在云原生环境下孕育出了很多优秀的项目。本文会简单介绍一下 Go 语言生态下的 dexidp/dex 和 ory/hydra ,感兴趣的可以自行到其官网详细了解。
dexidp/dex
Dex 作为 CNCF 的一个 sandbox 项目,是一个具有可插拔连接器的 OIDC 和 OAuth 2.0 提供商。
它通过”连接器“的身份来充当其他身份提供商的门户,可以将身份验证推送到 LDAP 服务器、SAML 提供商或 GitHub、Google 和 Active Directory 等其他一些成熟的身份提供商中进行验证。客户端只需写一次认证逻辑就可以与 Dex 对接,然后 Dex 来处理特定后端的协议。
ory/hydra
ORY Hydra 是一个 OAuth 2.0 和 OpenID Connect 提供者。
特别一说的是 Hydra 所实现的 OAuth 2.0 协议并不依赖 Go 标准库提供的,而是自实现的 fosite。
另外 ORY Hydra 还提供了一个 5 分钟的快速搭建教程。