DEV Community

JAGADEESH m
JAGADEESH m

Posted on

5

JWT Token Refresh: Authentication Made Simple 🔐

Why Do We Need Token Refresh?

Imagine you're playing an online game, and every 30 minutes, you get kicked out and have to log in again. Frustrating, right? In web applications, authentication works similarly. Tokens (like digital passes) expire for security reasons, but we want to make this process smooth for users.

The Problem with Traditional Authentication

When a token expires, most applications force you to log in again. This is like being midway through a task and suddenly being told to start over from scratch. Our goal is to fix this!

How Token Refresh Works: A Simple Explanation

Think of Tokens Like a Day Pass

  1. Access Token: A short-lived ticket that lets you enter different parts of an application
  2. Refresh Token: A special, longer-lasting ticket that helps you get a new access token

Image description

The Magic Happens in Two Steps

Step 1: Detect Token Expiration

// When a request fails because the token is old
Client.interceptors.response.use(
  (response) => response, // Normal responses pass through
  async (error) => {
    // Check if the error is because the token is expired
    if (error.response?.status === 401) {
      // It's like saying, "Oops, my pass is old. Let me get a new one!"
      const newToken = await refreshToken();
    }
  }
)
Enter fullscreen mode Exit fullscreen mode

Step 2: Get a New Token

const refreshToken = async () => {
  try {
    // Ask the server for a new access token
    const response = await Client.post("/auth/refresh", {
      withCredentials: true // Important security detail
    });

    // Extract the new token
    const { accessToken } = response.data;

    // Update the application with the new token
    updateToken(accessToken);

    return accessToken;
  } catch (error) {
    // If getting a new token fails, log the user out
    console.error("Couldn't refresh token");
    return null;
  }
};
Enter fullscreen mode Exit fullscreen mode

The Secret Sauce: Remembering the Original Request

// This is the magical part - saving the original request
const originalRequest = error.config;

// After getting a new token, replay the exact same request
if (newToken) {
  // It's like rewinding and replaying a game level
  originalRequest.headers.Authorization = `Bearer ${newToken}`;
  return Client(originalRequest);
}
Enter fullscreen mode Exit fullscreen mode

Real-World Analogy

Think of this like a multi-pass at an amusement park:

  • Your access token is a single-ride ticket
  • Your refresh token is the ability to get a new ride ticket
  • When a ride ticket (access token) expires, you use the multi-pass (refresh token) to get a new one
  • You don't have to leave the park or start over - you just get a new ticket!

Backend: Verifying the Refresh Token

const refresh = async (req, res) => {
  try {
    // Check if the refresh token exists
    const refreshToken = req.cookies.refreshToken;

    // Verify the token is valid and belongs to a real user
    const payload = jwt.verify(refreshToken, process.env.JWT_SECRET);

    // Find the user
    const user = await User.findOne({ email: payload.email });

    // Create a new access token
    const accessToken = jwt.sign({
      username: user.username,
      email: user.email
    }, process.env.JWT_SECRET, { expiresIn: "1d" });

    return res.status(200).json({ accessToken });
  } catch (error) {
    // Something went wrong
    return res.status(401).json({ message: "Authentication failed" });
  }
};
Enter fullscreen mode Exit fullscreen mode

Key Takeaways

  1. Token refresh keeps users logged in seamlessly
  2. We save the original request to replay it after getting a new token
  3. The process happens automatically in the background
  4. Users never know their token was refreshed

Pro Tips

  • Always use HTTPS to protect tokens
  • Implement proper error handling
  • Have a backup plan if token refresh fails

Conclusion

Authentication doesn't have to be complicated. With the right approach, you can create a smooth, secure experience that keeps your users happy and your application protected.

Happy Coding! 🚀🔐

Billboard image

Monitoring as code

With Checkly, you can use Playwright tests and Javascript to monitor end-to-end scenarios in your NextJS, Astro, Remix, or other application.

Get started now!

Top comments (2)

Collapse
 
deepakdharsh profile image
Deepakdharsh

It was very helpful

Collapse
 
surajkr86 profile image
surajkr86

I appreciate your post. I wish you the best in your learning journey! Thank you for your support.It is helpful.

Some comments may only be visible to logged-in visitors. Sign in to view all comments.

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Dive into an ocean of knowledge with this thought-provoking post, revered deeply within the supportive DEV Community. Developers of all levels are welcome to join and enhance our collective intelligence.

Saying a simple "thank you" can brighten someone's day. Share your gratitude in the comments below!

On DEV, sharing ideas eases our path and fortifies our community connections. Found this helpful? Sending a quick thanks to the author can be profoundly valued.

Okay