JWT — The Basics and more

Robert Lin
4 min readDec 1, 2016

--

JWT (pronounced ‘jot’) stands for JSON Web Token. It is defined in the standard RFC7519 published in May 2015. It is used to securely communicate JSON objects. Let’s dive into what a JWT is made of and why it’s important!

Here’s what a JWT consists of:

Header.Payload.Signature

Wow! So simple, right?

A Header typically consists of two things, the type of token and the hashing algorithm:

Header = { "typ": "JWT", "alg": "HS256" }

“JWT” here stands for JSON Web Token, as you can imagine. “HS256” stands for HMAC-SHA256 algorithm, a symmetric algorithm that uses a single secret key for the Signature. There are many other algorithms that can be used but other common ones include RSASSA-PKCS1-v1_5 + SHA256 (RS256) and ECDSA + P-256 + SHA256 (ES256), both which are asymmetric meaning they use a public/private key pair. There is also a “none” value available for “alg” which has been discovered to expose vulnerabilities in some JWT libraries.

Look at all these algorithms that JWT’s can use!! BEWARE OF “none” though!

The Payload contains the actual data and is also referred to as claims. An example is shown below with various bits of info in the object:

Payload = { "user_id": "0916", "admin": true, "iss": "robert.com" } 

There are three types of claims, reserved, public, and private. For the most part, public claims are used as they are defined by those using JWT’s. Reserved claims include “iss” for the issuer of the token, “aud” for the audience that the JWT is intended for, “sub” for the subject, and “exp” for the expiration time. They utilize three letters to keep the JWT compact. Private claims are custom claims that are agreed upon between the parties. However, you’re warned that they are subject to collision (when claim names match) and should be used with caution.

The Signature takes the encoded Header and encoded Payload, a secret key known only to the producer of the JWT (our server), the hash algorithm (i.e. HMAC-SHA256), and signs it.

signature = HMACSHA256(
base64UrlEncode(Header) + "." +
base64UrlEncode(Payload),
"some_secret_key"
);

What’s happening is the Header and Payload are encoded and joined with a “.”. Then, both encoded bits of info are then hashed with our HS256 algorithm and our secret key so aptly name “some_secret_key” to produce the signature. They all combine to form our JSON Web Token (actually encoded with https://jwt.io/#debugger)! This JWT can now be easily passed through HTML and HTTP environments.

base64UrlEncode(Header) => eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9base64UrlEncode(Payload) => eyJ1c2VyX2lkIjoiMDkxNiIsImFkbWluIjp0cnVlLCJpc3MiOiJyb2JlcnQuY29tIn0signature => HWmfTFIMIgCym7sVsH7O4SvCpqS5hvBi50Z_tNV9F7QJWT = eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiMDkxNiIsImFkbWluIjp0cnVlLCJpc3MiOiJyb2JlcnQuY29tIn0.HWmfTFIMIgCym7sVsH7O4SvCpqS5hvBi50Z_tNV9F7Q

Now the server just needs to provide the client with the JWT for future use. The client can now send this JWT along with its API requests to the server. Instead of having to authenticate a login, the server decodes the JWT (with its secret key) and verifies the identity of the client.

Here’s a simple analogy for what JWT is and how this validation process works. You’re a VIP going to concert of your favorite band. Your credentials are yourself and your ID (much like a username and password). The venue and the staff (server) have a guest list that contains your name on it (database). After presenting your credentials, you are given this magical wristband that proves your identity has been checked to the list and verified (JWT). You no longer need to be verified again since there is no other way to obtain these magical wristbands, and you are free to walk in and out of the venue until the concert has ended (JWT expiration — “exp”).

Why is this significant? It allows the server to verify the information within the JWT without having to store much. The server stores a single secret key in its database that is used to issue new tokens (encoding/encrypting) and decode all incoming JWT’s. This provides scalability as the server can respond faster to authentication requests; it doesn’t matter if you have one or one million users logged in at the same time, the same secret key will be used for authentication. This is in contrast to a traditional method of storing and creating a record in the database for every single user which means unique keys for each.

Do you ever need to change the secret key? This is a question I really pondered. Ideally you wouldn’t have to change the secret key because it’s secret and should be secured as most secret things are. A change in the key would require all users to be logged out (which sounds like a server reset of sorts to me) as the old issued JWT’s of users would be invalid with a new secret key.

The significance of these asymmetric algorithms are honestly a bit puzzling to me still, but it seems like the main reason to use asymmetric algorithms is when the origin of the JWT is important. In a public/private key scenario, only the issuer of the JWT has the private key to encode and encrypt while the public key is known to the outside. Thus, only the side with the private key can sign while everyone else has the ability to validate the signature with the public key. This way you know the issuer is legitimate as they are the only ones with the private (secret) key.

Here are some random things I noticed while learning about JWT. First, they are quite often referred to as JWT tokens. This practice suffers from RAS syndrome or “Redundant Acroynym Syndrome Syndrome” (HA!) as the “T” in JWT stands for Token. Calling it a JWT token is just like saying ATM machine or PIN number. Secondly, JWT is an acronym within an acronym (OMG Acronym-ception)! JWT stands for JSON Web Token and JSON itself stands for JavaScript Object Notation. Unfortunately JavaScript Object Notation Web Token is quite a mouthful so let’s just stick with “jot” 😀.

--

--

Robert Lin

Currently a Full Stack Web Development Student at Flatiron School. An avid problem solver looking to build web applications of the future!