Skip to content

JWT Auth Testing

JWT apps often store access tokens in localStorage or memory. Playwright tests can obtain tokens via API and inject them before navigation using addInitScript or storageState.

JWT Setup Patterns

Preferred: POST to /auth/login with request, save response tokens into storageState-compatible localStorage via setup script.

Alternative: page.addInitScript(({ token }) => localStorage.setItem('access_token', token), { token }) before goto.

test.beforeEach(async ({ page, request }) => {
  const res = await request.post('/api/auth/login', {
    data: { email: 'test@example.com', password: 'pass' },
  });
  const { accessToken } = await res.json();
  await page.addInitScript(token => {
    localStorage.setItem('access_token', token);
  }, accessToken);
  await page.goto('/dashboard');
});

addInitScript runs before page scripts on each navigation.

API Authorization Header

test.use({
  extraHTTPHeaders: {
    Authorization: `Bearer ${process.env.TEST_JWT}`,
  },
});
  • extraHTTPHeaders apply to page navigation and request fixture.
  • Test expired token by mocking time or using short TTL test JWT.
  • Refresh token flows may need route mock for /auth/refresh.
  • Never embed long-lived prod JWT in repo.

JWT Testing Recipes

Common JWT patterns.

Pattern Method
Token in localStorage addInitScript + goto
Bearer header only extraHTTPHeaders in config
API gets token request.post login
Expired token Inject expired JWT, expect logout
Invalid signature Malformed token → 401 UI
Refresh flow Mock refresh endpoint

storageState with JWT in localStorage

// After UI or API login that writes localStorage:
await page.context().storageState({ path: '.auth/jwt-user.json' });

JWT in APIRequestContext Headers

For API tests, set Authorization: Bearer ${token} in extraHTTPHeaders when obtaining a JWT from a login endpoint via request.post.

Common Mistakes

  • Setting localStorage after goto — app already redirected to login.
  • Hardcoded JWT that expires mid-suite in CI.
  • Not testing token refresh or 401 handling.
  • Confusing cookie session apps with JWT localStorage apps.

Key Takeaways

  • Obtain JWT via API; inject before navigation.
  • addInitScript seeds localStorage reliably.
  • Test expired and invalid token UX.
  • Use env vars for signing secrets in test token generation.

Pro Tip

Ask backend for a /test/session endpoint (dev-only) that returns valid JWT — cleaner than parsing login HTML in E2E.