Phase 3: Backend & APIs

JWT tokens, refresh tokens & session management

Intermediate ~3 min read
Think of it this way A friendly analogy. Read this if the technical version feels dense. Show Hide

Imagine you're at a super fun theme park. When you first arrive, you show your ticket, and they give you a special, brightly colored wristband. This wristband is like your "access pass." It instantly tells all the ride operators that you're allowed in and what rides you can go on – no need for them to check a big list every single time you want to get on a roller coaster. It's super fast! This quick check is really important because the park is huge, and there are tons of people, so every ride needs to check you quickly to keep things moving.

Now, these wristbands are awesome, but for safety, the park makes them expire very quickly, like every 15 minutes. Why? Well, if someone accidentally lost their wristband, you wouldn't want a stranger to be able to use it all day long and get on all the rides. So, after 15 minutes, your wristband glows and turns grey, meaning it's no good anymore. You could go all the way back to the main entrance to get a new one, but that would be super annoying and waste a lot of your ride time!

To fix this, when you first got your brightly colored wristband at the entrance, they also gave you a special, very secret laminated card. This card doesn't let you on rides directly; it's too boring for that. But, it's a "golden ticket" that you keep super safe in your pocket or wallet. When your bright wristband turns grey, you can quickly go to a small "Wristband Re-issue Booth" inside the park, show them your secret laminated card, and poof – they give you a brand new, bright wristband, good for another 15 minutes! You never have to leave the fun part of the park. This whole system, with the fast-checking wristbands and the secret re-issue cards, is how the park makes sure you have a smooth, fun, and safe day without constantly bothering you to prove who you are.

When building modern web applications, JWT (JSON Web Token) tokens are a cornerstone for stateless authentication. A JWT is a compact, URL-safe string that contains claims (information about an entity, e.g., a user ID or role) as a JSON object. This token is digitally signed by the server's private key, allowing the client to send it with every request, and the server to verify its authenticity and integrity without needing to query a database or maintain session state. This statelessness is incredibly beneficial for scalability, especially in distributed systems, as any server can validate any token. However, for security reasons, JWTs are typically short-lived (e.g., 15 minutes) to minimize the risk of compromise if intercepted, which would mean users frequently re-authenticating.

To address the short lifespan of access tokens and improve user experience, we introduce refresh tokens. A refresh token is a long-lived, securely stored token that's issued alongside the short-lived access token upon initial login. When an access token expires, the client can use the refresh token to request a new access token (and often a new refresh token too) from a dedicated endpoint, all without requiring the user to re-enter their credentials. This mechanism allows users to maintain their session for extended periods while still keeping the primary access tokens secure and short-lived. Refresh tokens are typically stored more securely (e.g., as HTTP-only cookies) and are usually checked against a server-side database for validity, allowing for revocation.

Together, JWTs and refresh tokens form a robust system for session management. The access token acts as the bearer token for accessing protected resources, while the refresh token's sole purpose is to renew access. When a user logs out, the refresh token should be revoked on the server to invalidate future requests for new access tokens. The client stores the access token (often in memory for SPA, or httpOnly cookie) and the refresh token (preferably in an httpOnly, secure cookie). This combination provides a secure, efficient, and scalable way to manage user sessions without relying on traditional server-side sessions, which helps offload database load and simplifies scaling.

Key Takeaways

  • JWTs are stateless access tokens, digitally signed, used for authenticating API requests and carrying user claims.
  • Refresh tokens are long-lived tokens used to securely obtain new, short-lived JWTs without requiring re-authentication.
  • Combining JWTs and refresh tokens enables secure, scalable, and stateless session management.
  • Access tokens grant immediate resource access; refresh tokens grant the ability to renew access.
  • Securely store tokens: Access tokens ideally in memory (SPA) or httpOnly cookie, refresh tokens in httpOnly, secure cookies.

Code Example

javascript
Preview

How this code works

This code's primary job is to demonstrate how to generate two essential tokens for secure user sessions: an accessToken and a refreshToken. It begins by setting up basic user information like userId and userRole, alongside a jwtSecret. This secret is critical; it's used to digitally sign the tokens, ensuring their authenticity. Notice the jwtSecret line: it attempts to fetch a secret from an environment variable but falls back to a development key. This fallback is a crucial detail, as in a real application, using a strong, secret environment variable is vital for security.

Next, the accessToken is created using jwt.sign(). This token includes the userId and userRole, and is given a short validity period with expiresIn: '15m'. A shorter lifespan means that even if an accessToken is stolen, it becomes invalid quickly, limiting potential damage. Following this, a refreshToken is generated, also using jwt.sign(). Refresh tokens typically contain less sensitive data, often just the userId, and are granted a much longer expiresIn: '7d' duration. This longer-lived refreshToken allows the application to issue a new accessToken once the old one expires, letting users stay logged in without needing to re-enter credentials frequently.