← Back to Blog

JSON Web Tokens (JWT): Authentication Guide

Complete guide to JWT authentication. Learn JWT structure, implementation, security best practices, and token refresh strategies.

Big JSON Team14 min readadvanced
B

Big JSON Team

Technical Writer

Expert in JSON data manipulation, API development, and web technologies. Passionate about creating tools that make developers' lives easier.

14 min read

What is JWT?

JSON Web Token (JWT) is a compact, URL-safe token format for securely transmitting information between parties.

JWT Structure

A JWT has three parts separated by dots:

header.payload.signature
{

"alg": "HS256",

"typ": "JWT"

}

Payload (Claims)

{

"sub": "1234567890",

"name": "John",

"iat": 1516239022,

"exp": 1516242622

}

Signature

Created by signing header + payload with secret key.

Standard Claims

  • sub: Subject (user ID)
  • iss: Issuer
  • aud: Audience
  • exp: Expiration time
  • iat: Issued at time
  • nbf: Not before

Implementation

Node.js

import jwt from 'jsonwebtoken';

const SECRET = process.env.JWT_SECRET;

// Create token

function createToken(user) {

return jwt.sign(

{ sub: user.id, email: user.email },

SECRET,

{ expiresIn: '1h' }

);

}

// Verify token

function verifyToken(token) {

try {

return jwt.verify(token, SECRET);

} catch (error) {

return null;

}

}

Python

import jwt

from datetime import datetime, timedelta

SECRET = os.environ['JWT_SECRET']

def create_token(user):

payload = {

'sub': user['id'],

'exp': datetime.utcnow() + timedelta(hours=1)

}

return jwt.encode(payload, SECRET, algorithm='HS256')

def verify_token(token):

try:

return jwt.decode(token, SECRET, algorithms=['HS256'])

except jwt.InvalidTokenError:

return None

Express Middleware

function authMiddleware(req, res, next) {

const token = req.headers.authorization?.split(' ')[1];

if (!token) {

return res.status(401).json({ error: 'No token' });

}

try {

req.user = jwt.verify(token, SECRET);

next();

} catch (error) {

res.status(401).json({ error: 'Invalid token' });

}

}

app.get('/protected', authMiddleware, (req, res) => {

res.json({ user: req.user });

});

Token Refresh Strategy

// Short-lived access token

function createAccessToken(user) {

return jwt.sign(

{ sub: user.id, type: 'access' },

ACCESS_SECRET,

{ expiresIn: '15m' }

);

}

// Long-lived refresh token

function createRefreshToken(user) {

return jwt.sign(

{ sub: user.id, type: 'refresh' },

REFRESH_SECRET,

{ expiresIn: '7d' }

);

}

Security Best Practices

  • Use strong secrets (256+ bits)
  • Set short expiration for access tokens
  • Validate all claims (algorithm, issuer, audience)
  • Store tokens securely (HttpOnly cookies)
  • Implement token revocation
  • Common Mistakes

    Don't Store Sensitive Data

    // ❌ Bad
    

    const token = jwt.sign({

    userId: 123,

    password: 'secret' // Never!

    }, secret);

    // ✅ Good

    const token = jwt.sign({

    sub: 123,

    role: 'user'

    }, secret);

    Always Validate Algorithm

    // ❌ Vulnerable
    

    jwt.verify(token, secret);

    // ✅ Secure

    jwt.verify(token, secret, { algorithms: ['HS256'] });

    Client-Side Token Handling

    class AuthService {
    

    async fetch(url, options = {}) {

    const token = localStorage.getItem('accessToken');

    const response = await fetch(url, {

    ...options,

    headers: {

    ...options.headers,

    'Authorization': Bearer ${token}

    }

    });

    if (response.status === 401) {

    await this.refreshToken();

    return this.fetch(url, options);

    }

    return response;

    }

    }

    Token Storage

    res.cookie('token', jwt, {
    

    httpOnly: true,

    secure: true,

    sameSite: 'strict',

    maxAge: 3600000

    });

    LocalStorage (Less Secure)

    localStorage.setItem('token', jwt);

    Conclusion

    JWT is powerful for stateless authentication. Use short expiration times, validate all claims, and never store sensitive data in the payload!

    Share:

    Related Articles

    Read in other languages