15 essential jwt (json web token) interview questions
JWT = A token string that server creates and sends to client. The JWT Flow: 1. User registers: sends email + password to server. 2. Server verifies credentials are valid. 3. Server CREATES a JWT token (digitally signed). 4. Server sends token to client. 5. Client stores in localStorage or cookies. 6. Next time: Client sends token with every request. 7. Server verifies the token signature. 8. If valid: Access granted. 9. If expired/tampered: Access denied.
JWT consists of Header.Payload.Signature. Example: eyJhbGc...OMjU.eyJzdW...NzE.SflKxw...2E305w. Header: Algorithm used (HS256). Payload: User data (id, email, role) - NOT encrypted, just encoded. Signature: Server's secret - prevents tampering. This structure allows the server to verify that the token hasn't been modified by the client.
Refresh tokens improve the user experience and provide security. We need two tokens: access token and refresh token. Access token has short expiry (15 min) and refresh token has long expiry (7 days). When access token expires, client sends refresh token to server, then server generates new access token with new signature and sends to client. User doesn't need to login again and can continue using the app.
Refresh token solves 2 problems: 1. User Experience: If only access token (15 min expiry), user has to login every 15 minutes — bad experience! Refresh token lets user stay logged in without re-entering password. 2. Security: If access token is stolen, hacker can use it for only 15 minutes. After 15 minutes, it's useless. Refresh token is stored safely, so safer overall. How it works: Access token (short-expiry) is used for API calls. Refresh token (long-expiry) is stored safely, used to get new access token. When access token expires, client sends refresh token to server, server creates new access token, client uses new token without re-logging in.
🍪 HTTP Cookie: Stored by browser & sent with every request automatically. Used for authentication to store session ID or refresh token. Has expiry time (session or persistent). Can be HttpOnly — cannot be accessed via JavaScript, protects from XSS attacks. Around 4KB limit. 🗄️ LocalStorage: Stores data permanently, remains even after browser close. Accessible via JavaScript (localStorage.getItem/setItem). No expiration by default, data stays until manually deleted. Larger storage (5-10MB). Not secure for sensitive data, vulnerable to XSS attacks. 📦 SessionStorage: Data persists only for tab session, cleared when tab/browser is closed. Works per tab (not shared between tabs). Accessible via JavaScript similar to localStorage. Larger than cookies (5-10MB). Used for temporary data (form data, temporary state).
RBAC stands for Role Based Access Control. Instead of giving permissions to individual users, we assign them roles — like admin, manager, user — and each role has specific permissions. For example admin can delete, manager can update, user can only read.
Authentication verifies who you are — like checking email and password. Authorization decides what you can do — like checking if you have admin role to delete a record. RBAC is an authorization mechanism.
I store role in JWT token so I don't need a database call on every request — middleware just reads the role from token directly. But there's a tradeoff — if role changes, old token still has old role until it expires. For highly sensitive apps, we can verify role from database on each request.
401 Unauthorized means the user is not authenticated — no token or invalid token, they need to login first. 403 Forbidden means user is authenticated but doesn't have permission — like a normal user trying to access admin route.
This is the JWT tradeoff — role is stored in token, so old token still works until expiry. Solutions are: use short-lived access tokens so role updates take effect quickly, or maintain a token blacklist in Redis, or check role from database on sensitive operations.
Yes — instead of single role string, we can store roles as an array in JWT and database. Like `roles: ['manager', 'editor']`. Then in middleware we check if user has any of the required roles.
RBAC is Role Based — permissions based on role. ABAC is Attribute Based Access Control — permissions based on attributes like time, location, department. RBAC is simpler and works for most apps. ABAC is more granular for complex systems.
No — role change should only be done by super admin or directly in database. Regular APIs should not expose role change endpoint, or if they do, it should be strictly protected by super admin access only.
JWT has a signature — if anyone tampers with the payload, signature verification fails and we reject the token. That's why JWT_SECRET must be kept private on the server.
We add it to the enum in schema, update middleware allowed roles, and create new routes for that role. It's very scalable — no need to change existing user permissions.