7. Creating and Validating JWTs
7.1. Creating a JWT
To create a JWT, the following steps are performed. The order of the steps is not significant in cases where there are no dependencies between the inputs and outputs of the steps.
-
Create a JWT Claims Set containing the desired claims. Note that whitespace is explicitly allowed in the representation and no canonicalization need be performed before encoding.
-
Let the Message be the octets of the UTF-8 representation of the JWT Claims Set.
-
Create a JOSE Header containing the desired set of Header Parameters. The JWT MUST conform to either the [JWS] or [JWE] specification. Note that whitespace is explicitly allowed in the representation and no canonicalization need be performed before encoding.
-
Depending upon whether the JWT is a JWS or JWE, there are two cases:
-
If the JWT is a JWS, create a JWS using the Message as the JWS Payload; all steps specified in [JWS] for creating a JWS MUST be followed.
-
Otherwise, if the JWT is a JWE, create a JWE using the Message as the plaintext for the JWE; all steps specified in [JWE] for creating a JWE MUST be followed.
-
-
If a nested signing or encryption operation will be performed, let the Message be the JWS or JWE, and return to Step 3, using a "cty" (content type) value of "JWT" in the new JOSE Header created in that step.
-
Otherwise, let the resulting JWT be the JWS or JWE.
7.2. Validating a JWT
When validating a JWT, the following steps are performed. The order of the steps is not significant in cases where there are no dependencies between the inputs and outputs of the steps. If any of the listed steps fail, then the JWT MUST be rejected -- that is, treated by the application as an invalid input.
-
Verify that the JWT contains at least one period ('.') character.
-
Let the Encoded JOSE Header be the portion of the JWT before the first period ('.') character.
-
Base64url decode the Encoded JOSE Header following the restriction that no line breaks, whitespace, or other additional characters have been used.
-
Verify that the resulting octet sequence is a UTF-8-encoded representation of a completely valid JSON object conforming to RFC 7159 [RFC7159]; let the JOSE Header be this JSON object.
-
Verify that the resulting JOSE Header does not contain duplicate Header Parameter names. When using a JSON parser that returns only the lexically last duplicate member name, as specified in Section 15.12 of ECMAScript 5.1 [ECMAScript], this step can be accomplished automatically.
-
Determine whether the JWT is a JWS or a JWE by examining the "enc" (encryption algorithm) Header Parameter in the JOSE Header.
-
If the "enc" Header Parameter is present, the JWT is a JWE.
-
Otherwise, the JWT is a JWS.
-
-
Depending upon whether the JWT is a JWS or JWE, there are two cases:
-
If the JWT is a JWS, follow the steps specified in [JWS] for validating a JWS using the algorithm in the JOSE Header and the key, and the JWS Payload and JWS Signature. Let the Message be the JWS Payload.
-
Otherwise, if the JWT is a JWE, follow the steps specified in [JWE] for validating a JWE using the algorithm in the JOSE Header and the key. Let the Message be the plaintext resulting from decryption.
-
-
If the JOSE Header contains a "cty" (content type) Header Parameter with a value of "JWT", then the JWT is a Nested JWT. In this case, return to Step 1, using the Message as the JWT.
-
Otherwise, base64url decode the Message following the restriction that no line breaks, whitespace, or other additional characters have been used.
-
Verify that the resulting octet sequence is a UTF-8-encoded representation of a completely valid JSON object conforming to RFC 7159 [RFC7159]; let the JWT Claims Set be this JSON object.
-
Verify that the JWT Claims Set does not contain duplicate Claim Names. When using a JSON parser that returns only the lexically last duplicate member name, as specified in Section 15.12 of ECMAScript 5.1 [ECMAScript], this step can be accomplished automatically.
Finally, note that when there are multiple keys available to an application, it may attempt to validate a JWS or JWE multiple times with different keys. If the application determines that the failure was due to using a specific key, it may continue to try other keys until successful or until all keys have been exhausted.
7.3. String Comparison Rules
Processing a JWT requires comparing JSON string values.
Comparisons for Claim Names and Header Parameter names are always performed as case-sensitive string comparisons without type conversion.
Comparisons of URIs in StringOrURI values and JSON string values are performed as follows:
-
If one value is a URI and the other is not a URI, the two values are different.
-
If both values are URIs, they are compared using case-sensitive string comparison without type conversion, canonicalization, or processing of backslash escapes.
-
If neither value is a URI, they are compared using case-sensitive string comparison without type conversion or processing of backslash escapes.
Note that for any given use case, more relaxed or more strict comparison rules might be appropriate for URIs and other strings, but these comparison rules MUST be explicitly specified.