JSON Web Token (JWT) 是一种紧凑,URL安全的方法,用于通信两端之间传递 claims 。在JWT中,claims 被编码成一个JSON 对象,在 JSON Web Sinature (JWS) 体系中,它充当payload, 在 JSON Web Encryption (JWE) 体系中,它充当
plaintext,通过消息鉴权编码(Message Authentication Code : MAC)或 加密的方式,使 claims 进行数字签名( digitally signed)和 完整的保护。
这是一份 Internet Standards 维护文档。这份文档由 Internet Engineering Task Force 撰写。它代表着 IETF 联盟的一致意见。它已经接受到了公众的反馈,得到了 Internet Engineering Steering Group (IESG) 的认可。 关于 Internet Standards
的更多信息请参阅 RFC 5741 文档的第 2 章节。关于这份文档当前状态的信息,任何勘误,和如何提供文档的反馈,可以在http://www.rfc-editor.org/info/rfc7519 找到.
JSON Web Token (JWT) 是一种简洁声明权限的呈现格式,运用于空间受限制的环境下,例如 HTTP Authorization headers 和 URI 查询参数。 JWTs 将 claims 编码成一个 JSON[RFC7159] 对象传输。在 JSON Web Signature (JWS) 体系中充当 payload,在 JSON Web Encryption (JWE) [JWE] 体系中充当 plaintext。通过消息鉴权编码 (Message Authentication Code:MAC) 或 加密的方式,让 claims 进行数字签名 (digitally signed) 或 完整的保护。JWTs 通常代表使用 JWS Compact Serializaiton 或者 JWE Compact Serialization。
JWT的英文发音建议和引文单词 “jot” 一样。
本文档使用的关键字 “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”,
“SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, 和 “OPTIONAL” 在文档 “Key words for use in RFCs to Indicate Requirement Levels” [RFC2119] 有描述。只有在术语以大写的形式出现时才表示它是术语,代表着特定含义。
这些术语由本文档定义:
JSON Web Token (JWT)
一个字符串,表示一组 claims 集合,构成一个 JSON 对象, 这个对象用 JWS 或者 JWE 编码, 使 claims 成为数字签名 (digitally signed) 或者 消息鉴权码 MACed(Message Authentication Code) 或加密。
JWT Claims Set
一个 JSON 对象,它包含由 JWT 传达的 claims。
Claim
一块由 subject 声称的信息。 一个 claim 表现为一对 name/value, 包含一个 Claim Name 和一个 Claim value。
Claim Name
Claim 表示法中的 name 部分。 一个 Claim Name 通常是一个string。
Claim Value
Claim 表示法中的 value 部分。 一个 Claim Value 可以是任意的 JSON value。
Nested JWT
一个 JWT 中采用了内嵌着 signing 和/或者 encryption。 在 Nested JWTs中,JWT 在 JWS 体系中作为 payload,在 JWE 体系中作为 plaintext。
Unsecured JWT
一个 JWT 它的 claims 并没有完全受保护或加密。
Collision-Resistant Name
namespace 中的 name, 用一种特有的方式分配 names,以避免同其他的 names 发生冲突。 collision-resistant namespaces 的例子包括: 域名, ITU-T X.660 和 X.670 Recommendation series 中定义的对象标识符 (Object Identifier: OIDs) , 和全局唯一标识符 (Universally Unique IDentifiers : UUIDs)[RFC4122] 。当使用一个行政等级代理的 namespace,name 的定义者负责采取措施,以确保 namespace 中使用他们定义的 name 是在可控制范围内。
StringOrURI
一个 JSON 字符串值, 只要满足附加的要求,可以使用任意的字符串值, 任何值只要包含一个 “:” 字符 MUST 是一个 URI [RFC3986]. StringOrURI 值是在比较的时候是大小写敏感的,并且没有进行任何转换和规范标准化。
JWTs 表示一个 claims 集合,构成一个 JSON 对象,编码在 JWS 和/或 JWE 结构中。这个 JSON 对象是一个 JWT Claims 集合。按照 RFC 7159 [RFC7159] 第四章节的定义,JSON 对象包含零个或者多个 name/value pairs(或者 members), 这里 names 是 strings, values 是任意 JSON 值。这些 members 是由 JWT 表示的 claims。 这个 JSON 对象可能包含空格 和/或 任何 JSON 值 之前或之后的换行符 或 结果字符串。与 RFC 7159[RFC7159]第2章节的定义一致。
JWT Claims 集合中的成员名叫做 Claim Names。与之对应的值叫做 Claim Values。
JOSE Header 的 文本内容记录了加密 JWT Claims Set 所使用的加密行为。 如果这个 JOSE Header 用于 JWS,那这个 JWT 就是一个 JWS, 它的 claims 是 数字签名 (digitally signed) 或者 消息鉴权码 (Message Authentication Code: MACed), 同 JWT Claims 集合在一起作为 JWS Payload。如果这个 JOSE Header 用于 JWE,那这个 JWT 就是一个 JWE, 她的 claims 是加密的, 和 JWT Claim 集合一起,作为 plaintext 被 JWE 加密。 一个 JWT 可能包含在 其他的 JWE 或者 JWS 结构中,以创建一个 Nested JWT, 允许嵌套签名和加密。
一个 JWT 代表着一系列用英文句号(’.’)分隔连接 URL-safe parts。每个 part 包含一个 base64url 加密的值。 JWT 中 parts 的数量依赖于 JWS 使用 JWS Compact Serialization 的输出结果,或 JWE 使用 JWE Compact Serialization 的输出结果。
下面的 JOSE Header 样例声明了这个编码对象是一个 JWT, 并且这个 JWT 是一个 JWS,并使用了消息鉴权编码(MACed), 使用的算法是HMAC SHA-256:
{"typ":"JWT",
"alg":"HS256"}
为了消除上面JSON 表示的对象的潜在歧义,下面使用 UTF-8 编码的八进制序列来表示同样的 JOSE header. (注意歧义的产生可能是因为不同系统平台换行符不同的表示方法(CRLF 或者 LF),在每行开头或结束使用不同的占位符, 最后一行是否使用换行符,还有其他原因。 在这个例子中,第一行没有前置或后置空格, 一个 CRLF 换行符 出现在第一行和第二行之间, 第二行有一个前置空格,没有后置空格, 最后一行没有终端换行符。) JOSE Header 用 UTF-8 编码,以八进制序列表示的内容如下(使用 JSON 数字符号):
[123, 34, 116, 121, 112, 34, 58, 34, 74, 87, 84, 34, 44, 13, 10, 32,
34, 97, 108, 103, 34, 58, 34, 72, 83, 50, 53, 54, 34, 125]
JOSE Header 用 UTF-8 编码,以八进制序列呈现的字符串,再用 Base64url 加密后的值为:
eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9
下面是一个 JWT Claims Set 的例子:
{"iss":"joe",
"exp":1300819380,
"http://example.com/is_root":true}
下面的八进制序列, 是上面的 JWT Claims Set 使用了 UTF-8 编码后的形式,就是 JWT Payload:
[123, 34, 105, 115, 115, 34, 58, 34, 106, 111, 101, 34, 44, 13, 10,
32, 34, 101, 120, 112, 34, 58, 49, 51, 48, 48, 56, 49, 57, 51, 56,
48, 44, 13, 10, 32, 34, 104, 116, 116, 112, 58, 47, 47, 101, 120, 97,
109, 112, 108, 101, 46, 99, 111, 109, 47, 105, 115, 95, 114, 111,
111, 116, 34, 58, 116, 114, 117, 101, 125]
用 Base64url 加密这个 JWS Payload 产生下面加密后的 JWS Payload(换行符仅仅是为了方便排版):
eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly
9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ
计算这个加密后的 JOSE Header 的 MAC, 用 HMAC SHA-256 算法加密 JWS Payload, 用 JWS 指定的方式加密这个 HAMC 值, 得到加密后的 JWS Signature:
dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
用英文句号(’.’)字符链接依顺序连接这些加密后的内容,得到完整的 JWT (换行符仅仅是为了排版的需要):
eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9
.
eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFt
cGxlLmNvbS9pc19yb290Ijp0cnVlfQ
.
dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
在 JWS 规范的 Appdendix A.1 中详细描述了这个计算过程。查阅 Appendix A.1 加密 JWT 的样例。
JWT Claims Set 表示一个 JSON 对象,它的成员是 JWT 传输的 claims。JWT Claims Set 中的 Claim Names MUST 是唯一的; JWT 解析器 MUST 拒绝拥有重复 member name 的 JWTs,或者使用 JSON 解析 只返回 重复的成员 name 的最后一个词汇,就像规范 ECMAScript 5.1 [ECMAScript] 的第 15.12 章节描述的那样。
一个 JWT 包含的 claims 必须是一组有效的,依赖上下文的。这方面的描述超出了本规范的范围。JWTs 特定的 applications 将要求实现某种特定的方法能够明白和处理某些claims。然而,缺乏某些要求,所有的 claims, 在实现时,如果不明白它的一生,就 MUST 被忽略。
这里有三种类型的 JWT Claim Names: Registered Claim Names, Public Claim Names, 和 Private Claim Names。
下面的 Claim Names 是在 IANA “JSON Web Token Claims” 登记的,在章节 10.1. 中约定俗称。就一切情况而论,下面定义的 claims 并不要求强制使用或实现。 而是在开始的时候提供一组使用的,有帮助的 claims。 Applications 使用 JWTs 应当定义他们使用哪些特定的claims,使用时是 required 还是 optional。所有的 names 都是简短的,因为 JWTs 的核心目标是表达形式简洁紧凑。
“iss” (issuer) claim 定义了发布这个 JWT 的当事人。 如何处理这个 claim 是通常的应用程序指定。 “iss” 的值是大小写敏感的字符串,包含一个 StringOrURI 值。使用这个 claim 是 OPTIONAL。
“sub” (subject) claim 定义了这个 JWT 的 subject。JWT中的 claims 通常是关于 subject 的陈述。subject 的值 MUST 是: issuer 上下文中的 scpoed,是本地唯一的,或者全局唯一的。如何处理这个 claim 通常是应用程序指定。”sub” 的值是大小写敏感的字符串,包含一个 StringOrURI 值。使用这个 claim 是 OPTIONAL。
“aud” (audience) claim 在 JWT 中用来标识收件人。每个打算处理 JWT 的当事人 MUST 在 audience claim 中用值来识别自己。如果有这个 claim,但处理这个 claim 的当事人无法用它的值识别自己,那么 MUST 拒绝这个JWT。 在一般情况下,”aud” 的值是有区分大小写的字符串构成的数组。每个字符串都包含一个 StringOrURI 值。在特殊情况下,当 JWT 只有一个 audience,”aud” 的值可能是一个大小写敏感的字符串,它包含一个 StringOrURI 值。audience 的值的解译一般由应用程序指定。使用这个 claim 是 OPTIONAL。
“exp” (expiration time) claim 标识了失效时间,当达到或超过这个时间时。JWT MUST NOT 接受和处理,处理 “exp” claim 要求当前的 date/time MUST 在 “exp” claim 标识的 date/time 之前。考虑到时钟差, 实现者 MAY 留有一点余地,通常不超过几分钟。它的值 MUST 是一个 number 类型,包含一个 NumericDate 值。使用这个选项是 OPTIONAL。
“nbf” (not before) claim 标识了时间点, 当早于这个时间点,JWT MUST NOT 被接受和处理。 处理这个 “nbf” claim 要求当前的 date/time MUST 在 “nbf” claim 所显示的 date/time 之后或者刚好在那个时间点。考虑到时钟差,实现者 MAY 留有一点余地,通常不超过几分钟。它的值 MUST 是一个 number 类型,包含一个 NumericDate 值。使用这个选项是 OPTIONAL。
“iat” (issued at) claim 标识了 JWT 所颁发的时间。这个 claim 能用于计算这个 JWT 已经使用的期限。它的值 MUST 是一个 number 类型,包含一个 NumericDate 值。使用这个选项是 OPTIONAL。
“jti” (JWT ID) claim 作为 JWT 的唯一标识符。这个标识符的值 MUST 指定,在某种意思上确保相同的值在极小概率的情况下分配给另一个不同的数据对象。如果应用程序使用多个 issuers,MUST 避免不同颁发者所产生的值可能一样的冲突。”jti” claim 可以用于避免 JWT 被重复发送。”jti” 的值是大小写敏感的。使用这个选项是 OPTIONAL。
Claim Names 可以被使用 JWTs 的人定义,然而,为了避免冲突,任何新的 Claim Name 应当满足:要么是 IANA “JSON Web Token Claims” registry 里面(在 10.1 章节里面制定)注册的值,要么是一个 Public Name:一个能够防止命名冲突的 Name。在各种情况下,定义 name 或者 value 的人需要警惕他们定义的 Claim Name 在 namespace 中能够得到控制。
JWT 的生产者和消费者可以约定他们所使用的 Claim Names 就是 Private Names:这些 names 既不是 Registered Claim Names(4.1 章节),也不是 Public Claim Names(4.2章节)。 不像 Public Claim Names,在使用Private Claim Names 应当谨慎,以防止引起冲突。
对于一个 JWT 对象来说,JSON 对象的成员 JOSE Header 描述了应用于 JWT 和 JWT 的可选属性,附加属性的加密操作。依赖于这个 JWT 是 JWS 还是 JWE,相应的规则应用于 JOSE Header 的值。本规范进一步指定了当JWT 是 JWS 或者 JWT 是 JWE 的情况下 Header Parameters 的使用。
由 [JWS] 和 [JWE] 定义的 Header Parameter 中的 “typ”(type) 参数用于在 JWT 应用程序中去声明这个完整JWT 的media type [IANA.MediaTypes]。这适用于 JWT 应用程序,当值不是 JWTs 时,同样可以包含一个 JWT 对象以表示应用程序的数据结构,应用程序可以使用这个值来消除不同对象可能存在的歧义。当 applications 已经知道这个对象是一个 JWT 时,applications 一般不会用它。这个参数在 JWT 的实现中将被忽略。任何对这个参数的处理将在 JWT 应用程序中进行。如果出现了, RECOMMENDED 它的值是 “JWT”, 以表名这个对象是一个 JWT。虽然 media type names 是大小写不敏感的,RECOMMENDED 它的值使用大写的 “JWT”,以和历史遗留的实现方式兼容。使用这个 Header Parameter 是 OPTIONAL。
本规范中用 [JWS] 和 [JWE] 定义的 “cty” (content type) Header Parameter 表示JWT的传输结构信息。在正常情况下,嵌套签名或加密操作无效。NOT RECOMMENDED 使用这个 Header Parameter。当使用了嵌套签名或加密时,MUST 使用这个 Header Prameter。在这种情况下,这个值 MUST 是 “JWT”, 以表明这个 JWT 包含一个 Nested JWT。虽然 media type names 不是大小写敏感的,RECOMMENDED “JWT” 直接用大写,以和遗留的系统兼容。参考 Appendix A.2 的 Nested JWT 样例。
在一些应用程序中使用加密的 JWTs,一些 claims 以未加密的形式呈现会很有用。这可能被利用,例如,应用程序在 JWT 加密前决定是否处理以及如何处理的步骤规则。
本规范允许 claims 在 JWT Claims Set 中重复出现,例如在充当 JWE 的 JWT 的 Header Parameters 中 ,根据应用程序的需要。如果出现这样的情况,应用程序接受到他们的时候 SHOULD 验证他们的值是否是一样的, 除非应用程序为处理这些 claims 定义了其他特定的处理规则。应用程序负责确保在没有加密的方式下传输是安全的 claims 才能在 JWT 的 Header Parameter 中重复出现。
本规范的章节 10.4.1 登记了 “iss” (issuer),
“sub” (subject), 和 “aud” (audience) Header Parameter names。用于提供加密的 JWTs 中的这些 claims 的未加密的复制版本,根据应用程序的需要。 如果需要的话,其他规范 MAY 注册其他的 names 作为 Header Parameter names 中的 Claim Names 。
为了支持用例:JWT content 在一种方法下是安全的,而不是用 签名 和/或 加密的方法包含在 JWT (例如 JWT 包含的数据结构中包含一个签名),JWTs MAY 同样以 singnature 或者 encryption 之外的方式创建。 一个 Unsecured JWT 是一个JWS使用了 “alg” Header 参数,它的值是 “none” 或者它的 JWS Signature 值是空串, 如同 JWA 规范里面定义的那样; 他是一个不安全的 JWS,用 JWT Claims Set 作为它的 JWS Payload。
下面的例子 JOSE Header 声明了这个加密的对象是一个 Unsecured JWT:
{"alg":"none"}
用 Base64url 加密这个 UTF-8 编码的八进制形式的 JOSE Header 产生出这个加密的 JOSE Header 值:
eyJhbGciOiJub25lIn0
下面是 JWT Claims Set 的样例:
{"iss":"joe",
"exp":1300819380,
"http://example.com/is_root":true}
用 Base64url 加密这个 UTF-8 编码的八进制的 JWT Claims Set 产生出加密的 JWS Payload (换行符仅仅是为了排版需要):
eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFt
cGxlLmNvbS9pc19yb290Ijp0cnVlfQ
这个加密的 JWS Signature 是一个空串。用英文逗号(’.’)将各个部分按顺序链接后产生出这个完整的 JWT (换行符仅仅是为了排版需要):
eyJhbGciOiJub25lIn0
.
eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFt
cGxlLmNvbS9pc19yb290Ijp0cnVlfQ
.
为了创建一个 JWT,需要执行下面的步骤。在不依赖步骤执行输入和输出的情况下,步骤的执行顺序不重要。
当验证一个 JWT 时,需要进行下面的步骤。在不依赖步骤执行输入和输出的情况下,步骤的执行顺序不重要。如果下面罗列步骤中的任何一步失败了,那么 JWT MUST 被拒绝 – 也就是说,应用程序将把它当作一次非法的输入。
处理一个 JWT 必然要求将知道的 strings 同 JSON 对象中成员和值进行比较。例如,检查到底是什么算法,Unicode string 编码的 “alg” 将同 JOSE Header 里面的成员名称进行对比,看里面是否有一个 Header Parameter name 和它一样。
在 RFC7159 规范的 8.3 章节中描述了 JSON 规则中处理 member name 的对比方式。由于单个 String 执行的操作只有一种:要么相等,要么不相等,对已知的字符串,相同的规则可以用于比较两个 member names 和 member values。
这些对比规则 MUST 应用于所有的 JSON string 对比,除非在这种情况下:member 的定义显式地调用了了不同的比较规则来比较 member values。在本规范中,只有 “type” 和 “cty” 的 member values 不需要使用这些对比规则。
一些应用程序可能以区分大小写的值得方式包含大小写敏感的信息,例如 “iss”(issuer) claim value 中的 DNS name 部分。在那些场景下,应用程序可能需要定义一个用于场景的代表公约的规范,以表示区分大小写的部分,例如将他们转换成小写,如果超过了一方可能需要产生相同的值,这样就可以比较。(然而,如果所有其他的消费者方接收生产者方发出逐字的任何值,而不试图以一个独立的生产方的值比较,那么这个情况下生产者使用对比规则将不重要。)
本节定义了哪些算法和特性在本规范中是强制实行的。使用本规范的应用程序能根据具体的实现需求加上他们要使用的额外算法和特征。例如,一个应用程序可能要求支持加密的 JWTs 和 Nested JWTs,然而其他的可能要求支持签名的 JWTs,一种使用了 Elliptic Curve Digital Signature
Algorithm (ECDSA) ,使用了 P-256 curve 和 the SHA-256 hash
algorithm (“ES256”).
在 JSON Web Algorithms[JWA] 中指定的 signature 和 MAC algorithms,遵守 JWT 的实现,只有 HMAC SHA-256 (“HS256”) 和 “none” MUST 实现。实现时 RECOMMENDED 同样 支持 RSASSA-PKCS1-v1_5 with the SHA-256 hash
algorithm (“RS256”) 和 ECDSA using the P-256 curve 和 the SHA-256
hash algorithm (“ES256”)。支持其他算法和 key sizes 是 OPTIONAL。
JWTs 的加密是 OPTIONAL。 如果一个实现提供了加密的能力,JWA 规范中指定的加密算法, 只有R SAES-PKCS1-v1_5 with 2048-bit keys
(“RSA1_5”), AES Key Wrap with 128- and 256-bit keys (“A128KW” and
“A256KW”), 和 the composite authenticated encryption algorithm using
AES-CBC and HMAC SHA-2 (“A128CBC-HS256” and “A256CBC-HS512”) MUST 满足规范得到实现.
对 Nested JWTs 的支持是 OPTIONAL。
这个规范记录了 URN “urn:ietf:params:oauth:token-type:jwt” 供应用程序使用, 声称 content types 使用 URIs (而不是,例如,media types) 以表明这个 content 关联的是一个 JWT。
E-mail:[email protected]
译者:Kado
版权:你可以任意拷贝,但不要抹去我的信息。 ;)