Role-Based Access ControlLesson 5.4
storing roles in JWT claims vs database lookups
JWT role claims, stale role problem, database role lookup on each request, hybrid approach, role change propagation, token revocation for role changes
Storing Roles: JWT Claims vs Database
JWT-based auth requires a decision: embed the user's role in the token payload, or query the database on every request to get the current role?
JWT claims (embed role in token):
- Pro: Zero database hit per request. Fast.
- Con: Role changes do not propagate until the token expires. If you revoke admin access, the user keeps it until their 1-hour token expires.
Database lookup:
- Pro: Always fresh. Role changes take effect immediately.
- Con: Database hit on every authenticated request. Cache with Redis to mitigate.
// Hybrid: verify JWT (cryptographic check), then fetch role from cache/DB
async function authenticateAndFetchRole(req, res, next) {
const token = extractToken(req);
const payload = jwt.verify(token, SECRET, { algorithms: ['HS256'] });
// Check Redis cache first (TTL: 5 min)
let role = await redis.get(`user:role:${payload.sub}`);
if (!role) {
const user = await User.findById(payload.sub, 'role');
role = user.role;
await redis.set(`user:role:${payload.sub}`, role, 'EX', 300);
}
req.user = { id: payload.sub, role };
next();
}The hybrid approach is the production standard: JWT for cryptographic identity verification (no DB needed), cached DB lookup for mutable properties like roles. Cache invalidation on role change keeps data fresh within seconds.
