Skip to content

Latest commit

 

History

History
137 lines (88 loc) · 9.09 KB

json_web_token_structure.md

File metadata and controls

137 lines (88 loc) · 9.09 KB

Cross-platform cryptography

JSON web token (JWT) structure

This chapter explains how a JSON web token (JWT) is build. For my example I'm using a signed token or so called JSON web signature or short JWS, in the following text I'm calling it just token.

I'm starting my course with a generated token and I think this way it is more easy to understand how it was generated. The token was generated by my browser based example xxx using the following parameter:

Running the program I'm receiving this long string:

ewogICAgImFsZyI6ICJSUzI1NiIsCiAgICAidHlwIjogIkpXVCIKfQ.ewogICAgInN1YiI6ICJKV1QgUlMyNTYgc2lnbmF0dXJlIiwKICAgICJpc3MiOiAiaHR0cHM6Ly9qYXZhLWNyeXB0by5naXRodWIuaW8vY3Jvc3NfcGxhdGZvcm1fY3J5cHRvLyIsCiAgICAiaWF0IjogMTYxMzU2NDExNSwKICAgICJleHAiOiAxNjEzNTY0MjM1Cn0.0m3BW1p03Ms4qS0B7j67TVA8xNrLIGyVF2H8Vit30ABEiV2S3b9WZ4nMH0lCHrhebonw4D_tFf3slpWFkGl3aA5M_RmdbugcgulKl1EZFZL_j4l3bOvMvSZf2orXHdEx0r0vGHd0OM2D_oF97mfGyw0nvMZrDwosNqdEkzEsnvr9N-FVqdGUdJkPznH_CII1JuL9cQlkWuiGD2MGWDZXG4hq1qymVhem1_eIdc8PlrO84_A9cTOnlsJI5FxaUrMtfEuDwvrstZiKN-PzNd32lsJxBjOwEbgJpqv2zw6SKfnNMmhbTu1VrXKYWapFPPUORfFoCWRaxbNQSWR2KaLlIQ

and I'm splitting this long string into 3 parts. Have a close look to the token and you will find out that the 3 parts are concatenated with a "." character, here are the three parts:

part 1: the token header:

ewogICAgImFsZyI6ICJSUzI1NiIsCiAgICAidHlwIjogIkpXVCIKfQ

part 2: the token payload:

ewogICAgInN1YiI6ICJKV1QgUlMyNTYgc2lnbmF0dXJlIiwKICAgICJpc3MiOiAiaHR0cHM6Ly9qYXZhLWNyeXB0by5naXRodWIuaW8vY3Jvc3NfcGxhdGZvcm1fY3J5cHRvLyIsCiAgICAiaWF0IjogMTYxMzU2NDExNSwKICAgICJleHAiOiAxNjEzNTY0MjM1Cn0

part 3: the signature of the token:

0m3BW1p03Ms4qS0B7j67TVA8xNrLIGyVF2H8Vit30ABEiV2S3b9WZ4nMH0lCHrhebonw4D_tFf3slpWFkGl3aA5M_RmdbugcgulKl1EZFZL_j4l3bOvMvSZf2orXHdEx0r0vGHd0OM2D_oF97mfGyw0nvMZrDwosNqdEkzEsnvr9N-FVqdGUdJkPznH_CII1JuL9cQlkWuiGD2MGWDZXG4hq1qymVhem1_eIdc8PlrO84_A9cTOnlsJI5FxaUrMtfEuDwvrstZiKN-PzNd32lsJxBjOwEbgJpqv2zw6SKfnNMmhbTu1VrXKYWapFPPUORfFoCWRaxbNQSWR2KaLlIQ

Now you may think "wow, a lot of characters, but how can I read them?". The answer is easy - just use a Base64Url decoder for the parts 1 and 2. For demonstration I'm using an online decoder like https://base64.guru/standards/base64url/decode and paste in the part 1 and part 2.

What is Base64Url encoding?

In the end the Base64Url encoding is a regular Base64 encoding but it is "web safe", means that some characters got exchanged to enable that the string can be used as a parameter in an internet URL. The "+" character is changed to "-" and the "/" character will be an "_" character. The third difference are the possible "=" characters in the end, they occur for padding and are stripped of for encoding and need to get padded when decoding. It is important to use this Base64Url encoding as it is mandatory for external verification!

This is the decoded part 1 = token header:

{
    "alg": "RS256",
    "typ": "JWT"
}

and here is the decoded part 2 = token payload:

{
    "sub": "JWT RS256 signature",
    "iss": "https://java-crypto.github.io/cross_platform_crypto/",
    "iat": 1613564115,
    "exp": 1613564235
}

Later we will deal with part 3 but for now we examine the first part, the token header. As you see the structure is a JSON (JavaScript Object Notation) that is system wide in use.

What are the contents of the token header?

The most important value in the header is the "alg" value that stands for the "algorithm" that was used to calculate the signature. As the signature will get verified later in a (maybe) different system the verification function needs to know that algorithm.

The first part of the alg is "RS" and points to a RSA based signature with a PKCS1.5 padding, the second part is the hashing algorithm in use ("256" = "SHA-256").

I give an overview about the standardized algorithms in the article JSON web token JWA algorithms.

The second value "typ" is not mandatory but explains that is a JSON web token.

In my example I used the "RS256" signature algorithm.

What are the contents of the token payload?

For my example I'm using 4 values that are part of the payload, but you are not restricted to any length or number of data you transport with the token. As the JWS is standardized by the IETF there are 7 predefined values and I'm using 4 of them but you are entirely free to use your own variables. In a lot of documents the payload is named as "Registered Claim Names" you find the meaning of them in the https://tools.ietf.org/html/rfc7519#section-4.1:

  • 4.1.1. "iss" (Issuer) Claim: the "iss" (issuer) claim identifies the principal that issued the JWT
  • 4.1.2. "sub" (Subject) Claim: the "sub" (subject) claim identifies the principal that is the subject of the JWT
  • 4.1.6. "iat" (Issued At) Claim: the "iat" (issued at) claim identifies the time at which the JWT was issued
  • 4.1.4. "exp" (Expiration Time) Claim: the "exp" (expiration time) claim identifies the expiration time on or after which the JWT MUST NOT be accepted for processing

So in my example the "iss" and the "sub" values are text fields that identify the one who generated the token ("https://java-crypto.github.io/cross_platform_crypto/"") and for what purpose("JWT RS256 signature").

Let's now examine the two values of "iat" and "exp". The first one is a number that stands for the number of seconds after 1.1.1970 and is often called Unix timestamp. Using an online converter like https://www.unixtimestamp.com/ you receive two values:

GMT 	        Wed Feb 17 2021 12:15:15 GMT+0000
Your Time Zone 	Wed Feb 17 2021 13:15:15 GMT+0100 (Mitteleuropäische Normalzeit)

So my sample token was issued on Wednesday, February 17th 2021 at 12:15:15 GMT time (that is in Germany "CET" 13:15:15).

Let's do the same for the "exp" value:

GMT 	        Wed Feb 17 2021 12:17:15 GMT+0000
Your Time Zone 	Wed Feb 17 2021 13:17:15 GMT+0100 (Mitteleuropäische Normalzeit)

We do see that the expiry time is exact 120 seconds or 2 minutes after the issuing time. The expiry value is very important to prevent from unwanted use of the token after the defined time span (here two minutes). It is up the programmer to check for the validity of the token [some libraries will do the check automatically but, as written, but that depends on the library in use].

My sample programs will do a manual check for the expiration time and please remember - the time base has to be the GMT-timezone and not any local time.

How is the signature being calculated?

Now we are checking the third value of our token - the signature. The signature is calculated by concatenating the (Base64Url encoded) header with a "." and (Base64Url encoded) payload, so you get this complete string:

ewogICAgImFsZyI6ICJSUzI1NiIsCiAgICAidHlwIjogIkpXVCIKfQ.ewogICAgInN1YiI6ICJKV1QgUlMyNTYgc2lnbmF0dXJlIiwKICAgICJpc3MiOiAiaHR0cHM6Ly9qYXZhLWNyeXB0by5naXRodWIuaW8vY3Jvc3NfcGxhdGZvcm1fY3J5cHRvLyIsCiAgICAiaWF0IjogMTYxMzU2NDExNSwKICAgICJleHAiOiAxNjEzNTY0MjM1Cn0

Using my RSA PKCS1.5 signature program with this string as input you receive this signature (that is Base64 encoded):

0m3BW1p03Ms4qS0B7j67TVA8xNrLIGyVF2H8Vit30ABEiV2S3b9WZ4nMH0lCHrhebonw4D/tFf3slpWFkGl3aA5M/RmdbugcgulKl1EZFZL/j4l3bOvMvSZf2orXHdEx0r0vGHd0OM2D/oF97mfGyw0nvMZrDwosNqdEkzEsnvr9N+FVqdGUdJkPznH/CII1JuL9cQlkWuiGD2MGWDZXG4hq1qymVhem1/eIdc8PlrO84/A9cTOnlsJI5FxaUrMtfEuDwvrstZiKN+PzNd32lsJxBjOwEbgJpqv2zw6SKfnNMmhbTu1VrXKYWapFPPUORfFoCWRaxbNQSWR2KaLlIQ==

Simply compare this (Base64 encoded) signature and you will notice that it looks like very similar to the one we see in part 3 of the token (see the part in the beginning of this article) - except for the necessary changes due to Base64Url encoding.

That looks like very simple and yes - it is as simple as described. For that reason I used the browser based Javascript example as a basis and done just some modifications to get a JWS signer and verifier.

How do we verify the signature?

Just exactly as you made the signature - build a string with (concatenated) header and payload and use the (matching) public key to verify the signature (after you decoded the Base64Url encoded signature :-).

What is the structure of a JSON JWE encrypted token?

The structure is a little more complicated due to the fact that a good encryption needs some random parameter that we need to decrypt the token later. Kindly see the article JSON web token JWE RSA-OAEP-256 encryption.

Last update: Feb. 21th 2021

Back to the main page: readme.md or back to the JSON web token overview page.