Course contentsShow
← Node.js
Lesson 1565 of 1,98014. Testing Methodologies and Quality AssuranceFree lesson

Validating JWT Expiration and Rotation

Test the full lifecycle of authentication tokens, including early expiration and renewal.

In this lesson, you will learn how to verify the entire lifecycle of a JSON Web Token (JWT) by testing both its automated expiration and its seamless rotation mechanism.

The Lifecycle Challenge

When managing JWTs, the system must enforce strict expiration times (exp claim) to limit the window of vulnerability if a token is intercepted. However, forcing a user to re-login every time a short-lived token expires provides a poor experience. We solve this with Rotation, where a secondary "refresh token" is used to exchange old credentials for a new, valid access token. Testing this flow is critical because it involves state changes on both the client (the token storage) and the server (the whitelist/blacklist of tokens).

Implementing Expiration and Rotation Tests

To test this, you need to simulate the passage of time without actually waiting. You can use libraries like sinon to fake the system clock, or simply generate tokens with hardcoded exp timestamps in the past.

Here is a conceptual integration test approach using jest and supertest:

it('should reject an expired token and succeed after rotation', async () => {
  // 1. Generate an expired token
  const expiredToken = generateToken({ exp: Date.now() - 10000 });

  // 2. Assert that access to a protected route fails
  const res = await request(app).get('/api/profile').set('Authorization', `Bearer ${expiredToken}`);
  expect(res.status).toBe(401);

  // 3. Perform rotation using a valid refresh token
  const refreshRes = await request(app).post('/auth/refresh').send({ refreshToken: validRefreshToken });
  expect(refreshRes.body).toHaveProperty('accessToken');
  
  // 4. Verify the new token grants access
  const finalRes = await request(app).get('/api/profile').set('Authorization', `Bearer ${refreshRes.body.accessToken}`);
  expect(finalRes.status).toBe(200);
});

Critical Test Scenarios

  • Clock Skew: Always test that tokens with an exp value a few milliseconds into the future are still accepted.
  • Refresh Token Reuse: If your security policy dictates that refresh tokens are one-time-use, simulate a scenario where a user tries to reuse an old refresh token to ensure the system invalidates the entire session.
  • Race Conditions: Ensure that simultaneous requests with an expiring token don't trigger multiple rotations, which could lead to token collisions.

Key Takeaway: Testing JWTs requires validating that your system rejects expired claims instantly while ensuring the rotation flow provides uninterrupted access without creating security loopholes through token reuse.