Overview
Protect routes with JWT authentication. Supports role-based access control.
Features
- JWT verification
- Role-based access control
- Token extraction from header/cookie
- Customizable error responses
Installation
npx hanma add jwt-auth
Dependencies
jsonwebtoken
Code
import { Request, Response, NextFunction } from 'express';
import jwt from 'jsonwebtoken';
const JWT_SECRET = process.env.JWT_SECRET || 'changeme-in-production';
/**
* Extended Request interface with user payload
*/
export interface AuthenticatedRequest extends Request {
user?: JwtPayload;
}
export interface JwtPayload {
id: string;
email: string;
role?: string;
[key: string]: unknown;
}
/**
* Extract JWT token from Authorization header
* Supports: "Bearer <token>" format
*/
const extractToken = (req: Request): string | null => {
const authHeader = req.headers.authorization;
if (!authHeader) return null;
// Support "Bearer <token>" format
if (authHeader.startsWith('Bearer ')) {
return authHeader.slice(7);
}
return authHeader;
};
/**
* JWT Authentication Middleware
* Verifies token and attaches decoded payload to req.user
*/
export const authenticate = (
req: AuthenticatedRequest,
res: Response,
next: NextFunction
) => {
const token = extractToken(req);
if (!token) {
return res.status(401).json({
success: false,
message: 'Access denied. No token provided.',
});
}
try {
const decoded = jwt.verify(token, JWT_SECRET) as JwtPayload;
req.user = decoded;
next();
} catch (error) {
if (error instanceof jwt.TokenExpiredError) {
return res.status(401).json({
success: false,
message: 'Token has expired.',
});
}
if (error instanceof jwt.JsonWebTokenError) {
return res.status(401).json({
success: false,
message: 'Invalid token.',
});
}
return res.status(500).json({
success: false,
message: 'Failed to authenticate token.',
});
}
};
/**
* Optional authentication - doesn't fail if no token provided
* Useful for routes that behave differently for logged-in users
*/
export const optionalAuth = (
req: AuthenticatedRequest,
res: Response,
next: NextFunction
) => {
const token = extractToken(req);
if (!token) {
return next();
}
try {
const decoded = jwt.verify(token, JWT_SECRET) as JwtPayload;
req.user = decoded;
} catch {
// Token invalid, but that's okay for optional auth
}
next();
};
/**
* Role-based authorization middleware
* Use after authenticate middleware
* @param allowedRoles - Array of roles that can access the route
*/
export const authorize = (...allowedRoles: string[]) => {
return (req: AuthenticatedRequest, res: Response, next: NextFunction) => {
if (!req.user) {
return res.status(401).json({
success: false,
message: 'Authentication required.',
});
}
if (!req.user.role || !allowedRoles.includes(req.user.role)) {
return res.status(403).json({
success: false,
message: 'Insufficient permissions.',
});
}
next();
};
};
Usage
import { authenticate, authorize } from './middleware/auth/jwt-auth';
app.get('/admin', authenticate, authorize(['admin']), handler);
Dependencies
jsonwebtoken
Frequently Asked Questions
How do I install JWT Authentication?
Run the following command:
npx hanma add jwt-authWhat dependencies are required?
This snippet requires: jsonwebtoken. Make sure to install them before using the snippet.
How do I use this snippet?
Copy the code and paste it into your project. The snippet will be saved to
middleware/auth/jwt-auth.ts.Can I customize this snippet?
Yes! All snippets are copy-paste code that you own. Feel free to modify them to fit your needs.
Does this work with other frameworks?
This snippet is designed for the specific framework. Check the other framework pages for equivalent implementations.