Best Practices for Designing and Implementing JWT Authentication with Claude Code
Learn about best practices for designing and implementing jwt authentication using Claude Code. Practical tips and code examples included.
JWT Authentication Fundamentals
JWT (JSON Web Token) is a token format that enables stateless authentication. With Claude Code, you can efficiently build a secure JWT authentication system.
Token Generation and Verification
import jwt from "jsonwebtoken";
import { z } from "zod";
const TokenPayloadSchema = z.object({
userId: z.string(),
email: z.string().email(),
role: z.enum(["admin", "user", "viewer"]),
});
type TokenPayload = z.infer<typeof TokenPayloadSchema>;
const JWT_CONFIG = {
accessSecret: process.env.JWT_ACCESS_SECRET!,
refreshSecret: process.env.JWT_REFRESH_SECRET!,
accessExpiresIn: "15m" as const,
refreshExpiresIn: "7d" as const,
};
function generateTokens(payload: TokenPayload) {
const accessToken = jwt.sign(payload, JWT_CONFIG.accessSecret, {
expiresIn: JWT_CONFIG.accessExpiresIn,
issuer: "my-app",
audience: "my-app-client",
});
const refreshToken = jwt.sign(
{ userId: payload.userId },
JWT_CONFIG.refreshSecret,
{
expiresIn: JWT_CONFIG.refreshExpiresIn,
issuer: "my-app",
}
);
return { accessToken, refreshToken };
}
function verifyAccessToken(token: string): TokenPayload {
const decoded = jwt.verify(token, JWT_CONFIG.accessSecret, {
issuer: "my-app",
audience: "my-app-client",
});
return TokenPayloadSchema.parse(decoded);
}
Authentication Middleware
import { Request, Response, NextFunction } from "express";
interface AuthenticatedRequest extends Request {
user?: TokenPayload;
}
function authMiddleware(
req: AuthenticatedRequest,
res: Response,
next: NextFunction
) {
const authHeader = req.headers.authorization;
if (!authHeader?.startsWith("Bearer ")) {
return res.status(401).json({ error: "No token provided" });
}
const token = authHeader.slice(7);
try {
const payload = verifyAccessToken(token);
req.user = payload;
next();
} catch (error) {
if (error instanceof jwt.TokenExpiredError) {
return res.status(401).json({
error: "Token expired",
code: "TOKEN_EXPIRED",
});
}
return res.status(401).json({ error: "Invalid token" });
}
}
Refresh Token Rotation
For enhanced security, issue a new refresh token on each refresh.
import { Redis } from "ioredis";
const redis = new Redis(process.env.REDIS_URL!);
async function refreshAccessToken(refreshToken: string) {
// Check if the refresh token has been revoked
const isRevoked = await redis.get(`revoked:${refreshToken}`);
if (isRevoked) {
throw new Error("Refresh token has been revoked");
}
const decoded = jwt.verify(refreshToken, JWT_CONFIG.refreshSecret) as {
userId: string;
};
// Fetch user info
const user = await getUserById(decoded.userId);
if (!user) {
throw new Error("User not found");
}
// Revoke old refresh token
await redis.set(
`revoked:${refreshToken}`,
"1",
"EX",
7 * 24 * 60 * 60
);
// Generate new token pair
const payload: TokenPayload = {
userId: user.id,
email: user.email,
role: user.role,
};
return generateTokens(payload);
}
Login Endpoint
import bcrypt from "bcrypt";
app.post("/auth/login", async (req, res) => {
const { email, password } = req.body;
const user = await getUserByEmail(email);
if (!user) {
return res.status(401).json({ error: "Invalid credentials" });
}
const isValid = await bcrypt.compare(password, user.passwordHash);
if (!isValid) {
return res.status(401).json({ error: "Invalid credentials" });
}
const payload: TokenPayload = {
userId: user.id,
email: user.email,
role: user.role,
};
const tokens = generateTokens(payload);
// Set refresh token as HttpOnly Cookie
res.cookie("refreshToken", tokens.refreshToken, {
httpOnly: true,
secure: true,
sameSite: "strict",
maxAge: 7 * 24 * 60 * 60 * 1000,
});
res.json({ accessToken: tokens.accessToken });
});
Security Considerations
Key points to watch for in JWT authentication. For overall security design, also see OAuth Authentication Implementation.
| Risk | Mitigation |
|---|---|
| Token leakage | Short expiration + refresh tokens |
| XSS | HttpOnly Cookie + CSP |
| CSRF | SameSite attribute + CSRF tokens |
| Replay attacks | jti claim + blacklist |
Using with Claude Code
When implementing JWT authentication tailored to your existing codebase, instruct Claude Code as follows. For productivity tips, see 10 Tips to 3x Your Claude Code Productivity.
Implement JWT authentication.
- Access token: 15 minutes, Refresh token: 7 days
- Refresh token rotation support
- Redis-based token blacklist management
- Integrate with the existing user model
For detailed JWT specifications, see RFC 7519. For Claude Code usage, refer to the official documentation.
Summary
JWT authentication offers the appeal of stateless design, but token management and security measures are critical. Implementing with Claude Code while understanding your entire project ensures a consistent authentication foundation.
Free PDF: Claude Code Cheatsheet in 5 Minutes
Just enter your email and we'll send you the single-page A4 cheatsheet right away.
We handle your data with care and never send spam.
Level up your Claude Code workflow
50 battle-tested prompt templates you can copy-paste into Claude Code right now.
About the Author
Masa
Engineer obsessed with Claude Code. Runs claudecode-lab.com, a 10-language tech media with 2,000+ pages.
Related Posts
7 Deployment Checks Before You Publish a Multilingual Claude Code Article Every Day
A practical checklist for publishing daily multilingual Claude Code articles without missing locales, breaking CTAs, or shipping stale pages.
Codex Automations for Content Ops: A Daily Revenue Workflow for Claude Code Sites
Use Codex Automations to turn analytics, article updates, CTA improvements, deployment, and verification into a daily revenue workflow.
Claude Code × GCP Cloud Functions Complete Guide | Rapid Serverless Function Development
Streamline GCP Cloud Functions with Claude Code. Implement HTTP/Pub/Sub/Firestore triggers, local testing, and deployment automation with real-world code examples from Masa's experience.
Related Products
The Complete Claude Code Setup & Configuration Guide
From install to team-ready workflow.
A practical guide to installation, CLAUDE.md, hooks, MCP servers, permissions, IDE setup, and CI/CD workflows.
50 Battle-Tested Claude Code Prompt Templates
Copy, paste, ship. 50 production-ready prompts.
Use proven prompts for code review, refactoring, testing, documentation, debugging, architecture, and incident response.