I am learning about JWTs and the way I have understood about JWTs is as follows (assuming we are using HS256
signing algorithm):
// pseudo code
HEADER = Base64Encoded(headerJSON)
PAYLOAD = Base64Encoded(payloadJSON)
SIGNATURE = HMACSHA256(`${HEADER}.${PAYLOAD}`, secret)
and finally JWT string is generated by joining all of the above:
JWT = `${HEADER}.${PAYLOAD}.${SIGNATURE}`
So, HEADER
and PAYLOAD
both are base64 encoded, but I am not sure about signature. I think we need SIGNATURE
to be base64 encoded as well as it will be safe for HTTP headers to include.
If it is encoded then do we do it manually? or HMACSHA256
algo automatically returns encoded version?
On the other hand if it is not encoded, then why do we not require it?
JWTs are defined by RFC7519 standard and its Section 1 describes:
[...] JWTs encode claims to be transmitted as a JSON object that is used as the payload of a JSON Web Signature (JWS) structure or as the plaintext of a JSON Web Encryption (JWE) structure [...] JWTs are always represented using the JWS Compact Serialization or the JWE Compact Serialization.
So a JWT is either represented as the JWS Compact Serialization or JWE Compact Serialization.
For non-encrypted JWT tokens, we use JWS structure which is defined by RFC7515 standard. Hence JWS Compact Serialization is used which is described in its Section-3.1
In the JWS Compact Serialization, a JWS is represented as the concatenation:
BASE64URL(UTF8(JWS Protected Header)) || '.' || BASE64URL(JWS Payload) || '.' || BASE64URL(JWS Signature)
An encoding example with HMACSHA256
signing algorithm is also provided in the Appendix-A.1
[...] Running the HMAC SHA-256 algorithm on the JWS Signing Input with this key yields this JWS Signature octet sequence:
[116, 24, 223, 180, 151, 153, 224, 37, 79, 250, 96, 125, 216, 173, 187, 186, 22, 212, 37, 77, 105, 214, 191, 240, 91, 88, 5, 88, 83, 132, 141, 121]
Encoding this JWS Signature as BASE64URL(JWS Signature) gives this value:
dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
So YES, the signature is Base64 encoded as per the specification and we need to manually encode it after running the signing algorithm.