7. 创建和验证 JWT (Creating and Validating JWTs)
7.1. 创建 JWT (Creating a JWT)
创建 JWT 时执行以下步骤. 当各步骤的输入和输出之间不存在依赖关系时, 步骤顺序并不重要.
-
创建一个包含所需声明的 JWT 声明集. 注意, 表示中明确允许空白, 并且在编码前不需要执行规范化.
-
令 Message 为 JWT 声明集的 UTF-8 表示的 octets.
-
创建一个包含所需头部参数集合的 JOSE 头部. JWT 必须符合 [JWS] 或 [JWE] 规范之一 (MUST). 注意, 表示中明确允许空白, 并且在编码前不需要执行规范化.
-
根据 JWT 是 JWS 还是 JWE, 存在两种情况:
-
如果 JWT 是 JWS, 则使用 Message 作为 JWS 载荷创建 JWS; 必须遵循 [JWS] 中规定的创建 JWS 的所有步骤 (MUST).
-
否则, 如果 JWT 是 JWE, 则使用 Message 作为 JWE 的明文创建 JWE; 必须遵循 [JWE] 中规定的创建 JWE 的所有步骤 (MUST).
-
-
如果将执行嵌套签名或加密操作, 则令 Message 为该 JWS 或 JWE, 并返回步骤 3, 在该步骤创建的新 JOSE 头部中使用值为 "JWT" 的 "cty" (content type).
-
否则, 令生成的 JWT 为该 JWS 或 JWE.
7.2. 验证 JWT (Validating a JWT)
验证 JWT 时执行以下步骤. 当各步骤的输入和输出之间不存在依赖关系时, 步骤顺序并不重要. 如果列出的任何步骤失败, 则必须拒绝该 JWT (MUST), 即应用应将其视为无效输入.
-
验证 JWT 至少包含一个句点 ('.') 字符.
-
令编码后的 JOSE 头部 (Encoded JOSE Header) 为 JWT 中第一个句点 ('.') 字符之前的部分.
-
对编码后的 JOSE 头部进行 Base64url 解码, 并遵循未使用换行、空白或其他附加字符的限制.
-
验证所得 octet 序列是一个完全有效 JSON 对象的 UTF-8 编码表示, 且符合 RFC 7159 [RFC7159]; 令 JOSE Header 为该 JSON 对象.
-
验证所得 JOSE 头部不包含重复的头部参数名称. 如果使用的 JSON 解析器只返回词法顺序上最后一个重复成员名称, 如 ECMAScript 5.1 [ECMAScript] 第 15.12 节所规定, 则此步骤可自动完成.
-
通过检查 JOSE 头部中的 "enc" (encryption algorithm) 头部参数, 确定 JWT 是 JWS 还是 JWE.
-
如果存在 "enc" 头部参数, 则 JWT 是 JWE.
-
否则, JWT 是 JWS.
-
-
根据 JWT 是 JWS 还是 JWE, 存在两种情况:
-
如果 JWT 是 JWS, 则按照 [JWS] 中规定的步骤, 使用 JOSE 头部中的算法和密钥以及 JWS 载荷和 JWS 签名来验证 JWS. 令 Message 为 JWS 载荷.
-
否则, 如果 JWT 是 JWE, 则按照 [JWE] 中规定的步骤, 使用 JOSE 头部中的算法和密钥来验证 JWE. 令 Message 为解密得到的明文.
-
-
如果 JOSE 头部包含值为 "JWT" 的 "cty" (content type) 头部参数, 则该 JWT 是嵌套 JWT. 在这种情况下, 使用 Message 作为 JWT 返回步骤 1.
-
否则, 对 Message 进行 Base64url 解码, 并遵循未使用换行、空白或其他附加字符的限制.
-
验证所得 octet 序列是一个完全有效 JSON 对象的 UTF-8 编码表示, 且符合 RFC 7159 [RFC7159]; 令 JWT 声明集为该 JSON 对象.
-
验证 JWT 声明集不包含重复的声明名称. 如果使用的 JSON 解析器只返回词法顺序上最后一个重复成员名称, 如 ECMAScript 5.1 [ECMAScript] 第 15.12 节所规定, 则此步骤可自动完成.
最后注意, 当应用有多个可用密钥时, 它可以使用不同密钥多次尝试验证 JWS 或 JWE. 如果应用确定失败是由于使用了某个特定密钥, 则可以继续尝试其他密钥, 直到成功或所有密钥都已用尽.
7.3. 字符串比较规则 (String Comparison Rules)
处理 JWT 需要比较 JSON 字符串值.
对声明名称和头部参数名称的比较始终作为区分大小写的字符串比较执行, 不进行类型转换.
对 StringOrURI 值中的 URI 和 JSON 字符串值的比较按如下方式执行:
-
如果一个值是 URI 而另一个不是 URI, 则两个值不同.
-
如果两个值都是 URI, 则使用区分大小写的字符串比较, 不进行类型转换、规范化或反斜杠转义处理.
-
如果两个值都不是 URI, 则使用区分大小写的字符串比较, 不进行类型转换或反斜杠转义处理.
注意, 对于任何给定用例, 对 URI 和其他字符串采用更宽松或更严格的比较规则都可能是合适的, 但这些比较规则必须被明确规定 (MUST).