不透明令牌与 JWT
了解不透明令牌和 JWT 之间的区别、它们的使用场景以及它们在基于 OIDC 的系统中如何被验证。
在 Logto 这样的基于 OIDC 的综合 CIAM 平台中,授权令牌在保障用户互动和管理访问资源方面起着至关重要的作用。在授权中使用的各种令牌中,不透明令牌和 JWTs(JSON Web Tokens)是最重要的。
我们收到了社区的几个问题,如:不透明令牌与 JWT 的区别是什么?我为什么不能解码收到的访问令牌,为什么令牌长度看起来很短?这篇博客文章旨在澄清这些概念,帮助你了解不透明令牌和 JWT 的区别、使用场景,以及为什么在使用它们时可能会遇到不同的行为。
什么是不透明令牌?
不透明令牌是一种访问令牌,顾名思义,对客户端或任何外部方来说都是不透明的或不可见的。这意味着令牌本身不携带关于用户或授予权限的任何可读信息。
当你收到一个不透明令牌时,它通常看起来是一个看似随机的字符串,尝试解码它不会产生任何有意义的数据。
这是一个不透明令牌的示例:
由于令牌的实际内容只有签发它的授权服务器知道,为了验证不透明令牌,客户端必须将其发送回服务器,服务器然后验证其真实性并确定相关的权限。这种方法确保了敏感信息保持隐藏,提供了额外的安全层,但它也需要额外的服务器通信来验证令牌。
优点:
- 安全:不透明令牌不向客户端暴露任何敏感信息。令牌的内容只有授权服务器知道。
- 可撤销:由于令牌存储在服 务器上,并且验证它的唯一方法是通过授权服务器上的内省端点,服务器可以轻松撤销令牌,并防止未经授权的访问。
- 小尺寸:不透明令牌通常比 JWTs 短,这对性能和存储有利。
缺点:
- 有状态:不透明令牌要求授权服务器维护状态以验证令牌,这可能会带来额外的复杂性和开销。
- 性能:需要额外的服务器通信来验证令牌可能会影响性能,特别是在高流量场景下。
什么是 JWT?
与不透明令牌相比,JWT(JSON Web Token)是一种自包含的、无状态的令牌,以结构化和可读的格式携带信息。
JWT 由三部分组成:header
,payload
和 signature
,每部分都以 Base64URL 编码。
这是一个 JWT 的示例:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
header
包含有关令牌类型和用于签名的算法的信息。例如,{"alg": "HS256", "typ": "JWT"}
。payload
包含声明 - 关于用户或授权的信息片段,如用户 ID、过期时间和范围。因为这些数据是编码的,但不是加密的,任何拥有令牌的人都可以解码以查看这些声明,尽管他们不能更改它而不无效化签名。根据规范和授权服务器配置,各种声明可以包含在有效负载中。这赋予了令牌其自包含的性质。例如,{"sub": "1234567890", "name": "John Doe", "iat": 1516239022}
。signature
是通过将头、有效负载和一个密钥使用指定的算法组合产生的。此签名用于验证令牌的完整性,并确保其未被篡改。
JWTs 很常用,因为它们可以由客户端或任何服务本地验证,而无需与授权服务器交互。这使得 JWTs 特别适用于分布式系统,这里多个服务可能需要独立验证令牌的真实性。
然而,这种便利也伴随着确保令牌声明不被过多暴露的责任,因为任何拥有令牌访问权的人都可以看到它们。此外,JWTs 通常寿命短,过期时间包含在令牌声明中,以确保令牌不会无限期有效。
优点:
- 无状态:JWTs 是自包含的,无需服务器端状态即可验证。
- 跨服务兼容:JWTs 可以很容易地在不同服务之间共享和验证,使其非常适合分布式系统。
- 可拓展:JWT 的有效负载可以包含自定义声明,允许灵活的授权和信息共享。
- 标准化:JWT 令牌遵循一个定义良好的标准(RFC 7519),使其受到广泛支持和互操作。
缺点:
- 曝露:JWT 中的声明对任何拥有令牌的人都是可见的,因此敏感信息不应包含在有效负载中。
- 大尺寸:由于携带的额外信息,JWTs 可能比不透明令牌大,这会影响性能和存储考虑。JWTs 中的声明应保持在最低限度以减少令牌大小。
- 撤销复杂性:由于 JWTs 是无状态的,通常是短期有效,而且没有内建机制在过期前撤销令牌,意味着一个被泄露的令牌可能会在到期前仍然有效。
不透明访问令牌验证
不透明访问令牌通过将其发送回授权服务器进行验证。授权服务器维护已签发令牌的状态,并可以根据其内部存储确定令牌的有效性。
- 客户端从授权服务器请求访问令牌。
- 授权服务器签发不透明令牌。
- 客户端在头部携带不透明令牌发送资源访问请求。
- 资源提供者发送令牌内省请求到授权服务器进行验证。
- 授权服务器回应令牌信息。
JWT 访问令牌验证(离线)
JWT 访问令牌可以由拥有令牌公钥的客户端或任何服务离线验证。
- 资源提供者预取授权服务器的公钥可以从 OIDC 发现端点进行,公钥用于验证令牌的签名并确保其完整性。
- 客户端从授权服务器请求访问令牌。
- 授权服务器签发 JWT 令牌。
- 客户端在头部携带 JWT 令牌发送资源访问请求。
- 资源提供者使用从授权服务器获取的公钥解码并验证 JWT 令牌。
- 资源提供者基于令牌的有效性授予访问权限。
OIDC 中的使用场景
在 OIDC(OpenID Connect)的上下文中,不透明令牌和 JWT 出于不同目的和用于不同场景。
不透明令牌
- 用户资料获取:
默认情况下,当客户端在请求访问令牌时未指定资源并包括 openid
范围,授权服务器会签发一个不透明的访问令牌。此令牌主要用于从 OIDC /oidc/userinfo
端点获取用户资料信息。在收到带有不透明访问令牌的请求后,授权服务器检查其内部存储以获取关联的授权信息并验证令牌的有效性,然后返回用户资料详情。
- 刷新令牌交换:
刷新令牌通过设计仅在客户端与授权服务器之间交换,无需与资源提供者共享。因此,刷新令牌通常以不透明令牌形式签发。当当前访问令牌过期时,客户端可以使用不透明刷新令牌获取新访问令牌,确保持续访问而无需重新认证用户。
JWTs
- ID 令牌:
在 OIDC 中,ID 令牌是一种 JWT,包含用户信息并用于验证用户身份。通常与访问令牌同时签发,ID 令牌允许客户端验证用户身份。例如:
客户端可以验证 ID 令牌以确保用户身份并提取用户信息用于个性化或授权目的。ID 令牌仅限一次性使用,不应用于 API 资源授权。
- API 资源访问:
当客户端请求带有特定资源指示的访问令牌时,授权服务器签发一个用于访问该资源的 JWT 访问令牌。JWT 包含资源提供者可用于授权客户端访问的声明。例如:
资源提供者可以通过检查声明来验证请求:
iss
:确认该令牌由受信的授权服务器发行。sub
:识别与令牌关联的用户。aud
:确保令牌用于特定资源。scope
:验证授予用户的权限。
结论
总之,不透明令牌和 JWT 在基于 OIDC 的系统中服务于不同的目的,不透明令牌提供了一种安全和有状态的授权方法,而 JWT 提供了一种自包含和无状态的替代方案。理解这些令牌类型及其使用场景之间的区别对于设计安全和高效的认证和授权机制至关重要。
在 Logto 中发现更多访问令牌特性: