Back to Blog
Backend

JWT and Refresh Tokens: What I Actually Learned

After implementing auth at Mapersive, here is how I now think about token lifecycles, rotation, and secure session management.

2024-02-142 min read
#JWT#Authentication#Backend#Security#Django

Before I Built It

I had used JWTs before — mostly by following tutorials that ended at "store it in localStorage, send it in the Authorization header." That gets you a working demo. It does not get you a secure system.

Building auth from scratch at Mapersive forced me to think through the full lifecycle.

The Basic JWT Flow

A JWT is a signed token containing claims — user ID, role, expiry. The server signs it; the client stores it and sends it back on every request.

The problem: JWTs cannot be invalidated before expiry. If a token is stolen, the attacker has access until the token expires.

Why Refresh Tokens

The solution is to use two tokens:

  1. Access token — short-lived (15 minutes). Sent with every API request.
  2. Refresh token — long-lived (7 days). Sent only to get a new access token pair.

This limits the damage window for a stolen access token while keeping the user experience smooth.

Refresh Token Rotation

Rotation means: every time you use a refresh token, you get a new one and the old one is invalidated.

In Django with simplejwt:

SIMPLE_JWT = {
    "ROTATE_REFRESH_TOKENS": True,
    "BLACKLIST_AFTER_ROTATION": True,
}

Logout and Blacklisting

JWTs are stateless, but logout requires state. A blacklist table of invalidated refresh token JTIs solves this.

Token Storage

The most debated part:

  • localStorage: Vulnerable to XSS
  • httpOnly cookie: Not accessible to JavaScript, but introduces CSRF considerations
  • Memory: Safest against XSS, but lost on page refresh

I used httpOnly cookie for the refresh token and memory for the access token.

What I Would Tell My Past Self

  • Short-lived access tokens are not optional if you care about security
  • Rotation is not extra complexity — it is the minimum for a responsible implementation
  • Token storage decisions are tradeoffs, not best practices