4 min read

Understanding JWT Tokens: A Beginner's Guide to JSON Web Tokens

Unlock JWTs: tiny, signed secrets for logins & trust. See their magic—header, payload, signature—click into place. Play at jwt.io. Your dev superpower awaits!
Understanding JWT Tokens: A Beginner's Guide to JSON Web Tokens

What Are JWT Tokens?

JWT (apparently pronounced "jot" but I like to pronounce it as 'J-W-T') stands for JSON Web Token. It's a modern way to safely pass information between two parties in a compact, self-contained format. What makes JWTs special is that they're digitally signed, which means you can trust the information they contain.

Why Are JWTs Useful?

JWTs shine in several common situations:

  1. Login systems: After logging in, your app can include the JWT with each request to prove who you are.
  2. Single Sign-On: Log in once and access many different services.
  3. Sharing information: Send data between systems with confidence it hasn't been tampered with.

The Three Parts of a JWT

Every JWT is made up of three sections, separated by dots:

header.payload.signature

Let's look at each part:

The Header

The header tells us two things: what type of token this is (JWT) and which method was used to sign it. It looks like this:

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

This gets converted to a special format called Base64Url, making it safe to include in web addresses and headers.

The Payload

The payload holds the actual information or "claims" you want to share. Claims are simply statements about a user or other data.

There are three types of claims:

  1. Standard claims: These are recommended claims with specific meanings:
    • iss (issuer): Who created the token
    • exp (expiration time): When the token expires
    • sub (subject): Who the token is about
    • aud (audience): Who the token is intended for
    • iat (issued at): When the token was created
  2. Public claims: These are claims defined by the people using JWTs but should be registered in the IANA JWT Registry or defined as a URI to avoid naming conflicts.
  3. Private claims: These are custom claims created specifically for sharing information between parties who have agreed on what they mean.

Here's an example of a payload with different types of claims:

{
  "iss": "auth.myservice.com",  
  "sub": "user12345",        
  "name": "Sarah Smith",     
  "role": "editor",          
  "exp": 1716057600,          
  "iat": 1715452800
}

In this example:

  • iss and sub are standard claims identifying the issuer and subject
  • exp is a standard claim showing when the token expires
  • iat is a standard claim showing when the token was issued
  • name and role are private claims with custom information

Important: Anyone can read this section by decoding it, so never put secrets or passwords here!

The Signature

The signature is created by combining:

  • The encoded header
  • The encoded payload
  • A secret key
  • The signing method mentioned in the header

For example:

HMACSHA256(
  encodedHeader + "." + encodedPayload,
  "your-secret-key"
)

This signature serves two important purposes:

  1. It proves the token hasn't been changed
  2. It confirms the sender is genuine (especially when using public/private key pairs)

How JWTs Work in Real Life

  1. You log in to a website with your username and password
  2. The server creates a JWT with information about you and signs it
  3. The server sends this JWT to your browser
  4. Your browser stores the JWT somewhere safe
  5. The server checks the signature to make sure it's valid
  6. If it's valid, the server fulfils your request

For future requests, your browser sends the JWT, typically in a header:

Authorization: Bearer eyJhbG...

Creating a Token in Code

Here's a simple example of how to create and verify a JWT token using JavaScript with the popular jsonwebtoken library:

const jwt = require('jsonwebtoken');

// Creating a token
function createToken() {
  // Define our payload
  const payload = {
    iss: "auth.myservice.com",
    sub: "user12345",
    name: "Sarah Smith",
    role: "editor",
    iat: Math.floor(Date.now() / 1000),
    exp: Math.floor(Date.now() / 1000) + (60 * 60) // 1 hour from now
  };

  // Your secret key (keep this safe!)
  const secretKey = "your-secret-key-keep-it-safe";

  // Create the token
  const token = jwt.sign(payload, secretKey);
  
  return token;
}

// Verifying a token
function verifyToken(token) {
  const secretKey = "your-secret-key-keep-it-safe";
  
  try {
    // This will throw an error if the token is invalid
    const decoded = jwt.verify(token, secretKey);
    console.log("Token is valid!");
    console.log(decoded);
    return true;
  } catch(error) {
    console.error("Token verification failed:", error.message);
    return false;
  }
}

// Usage
const myToken = createToken();
console.log("My JWT token:", myToken);

// Later when we receive a token
verifyToken(myToken);

This code shows how you can:

  1. Create a token with claims about a user
  2. Sign it with a secret key
  3. Later verify that token is authentic and not expired

Checking vs Verifying a JWT

These are two different but related security steps:

  • Checking (validation) makes sure the token is properly formed:
    • Has all three parts
    • Contains the expected information
    • Hasn't expired
    • Follows the proper format
  • Verifying confirms the token is authentic:
    • The signature matches what's expected
    • It comes from a trusted source
    • It hasn't been tampered with

Creating vs Reading a JWT

  • Creating (encoding) involves:
    1. Forming the header and payload as JSON
    2. Converting them to Base64Url format
    3. Creating a signature using your secret key
    4. Joining all three parts with dots
  • Reading (decoding) involves:
    1. Splitting the token at the dots
    2. Converting the first two parts back to readable JSON
    3. Optionally checking the signature

Keeping JWTs Secure

  1. Don't store sensitive data in the payload – it's easy to read
  2. Always use HTTPS to prevent tokens being stolen
  3. Keep tokens short-lived with reasonable expiry times
  4. Don't keep tokens longer than needed
  5. Don't store important session data in your browser
  6. Watch out for size limits – tokens in headers shouldn't exceed 8KB

Try It Yourself

To see JWTs in action and experiment with them, visit jwt.io. Their debugger tool lets you:

  • Break down and examine JWTs
  • Create your own tokens
  • See how signatures work

Ready to Dive Deeper Into JWTs?

Maybe you’ve been using JWT tokens in your projects for a while—tossing them into headers or passing them between systems—without fully grasping what’s going on under the hood. Well, now that you’ve got the basics under your belt, it all makes sense, right? You can see how those headers, payloads, and signatures come together to keep things secure and trustworthy. And the best part? You’re ready to take it further! Head over to jwt.io to play around with their awesome debugger tool. You can break down real JWTs, whip up your own tokens, and watch firsthand how signatures tie it all together—it’s like a sandbox for token enthusiasts!

Whether you’re fine-tuning a login system, exploring single sign-on, or just geeking out over secure data sharing, JWTs are a powerful tool to have in your toolkit. So go ahead, experiment, and have fun with it. Now that you get how they work, maybe you’ve got some fresh ideas brewing—why not share them with friends or jump into a dev community? There’s always more to discover, and I’d love to hear how it clicks for you now that the mystery’s unravelled!