TL;DR
This guide shows you how to add secure user authentication to your application using JSON Web Tokens (JWTs). We’ll cover creating tokens, verifying them, and protecting routes. It assumes basic knowledge of APIs and server-side programming.
1. Choose a JWT Library
First, select a suitable library for your chosen language/framework. Here are some popular options:
- Node.js:
jsonwebtoken - Python:
PyJWT - PHP:
firebase/php-jwt
Install the library using your package manager (e.g., npm, pip, composer).
2. User Registration & Login
- Implement user registration to create new accounts and store credentials securely (hashed passwords!).
- Implement a login endpoint that verifies user credentials against the stored data.
3. Create JWTs on Successful Login
When a user successfully logs in, generate a JWT containing user information.
// Example using Node.js and jsonwebtoken
const jwt = require('jsonwebtoken');
function generateToken(user) {
const payload = { userId: user.id, username: user.username }; // Data to store in the token
const secretKey = 'your-secret-key'; // Keep this VERY secure!
const options = { expiresIn: '1h' }; // Token expiry time
return jwt.sign(payload, secretKey, options);
}
Important: Never store sensitive information directly in the JWT payload that isn’t already publicly accessible. The token is easily decoded.
4. Send the JWT to the Client
After generating the token, send it back to the client (e.g., as a JSON response).
// Example Response:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
The client should store this token securely (e.g., in local storage or a cookie). Avoid storing it in plain text.
5. Protect API Routes with JWT Verification
- For each protected route, extract the JWT from the request header (usually
Authorization: Bearer <token>). - Verify the token’s signature using your secret key.
- If verification fails, return an error response (e.g., 401 Unauthorized).
- If verification succeeds, extract user information from the token payload and use it to authorize access.
// Example Node.js middleware:
function verifyToken(req, res, next) {
const authHeader = req.headers['authorization'];
if (!authHeader) {
return res.status(401).json({ message: 'No token provided.' });
}
const token = authHeader.split(' ')[1]; // Bearer token format
jwt.verify(token, 'your-secret-key', (err, decoded) => {
if (err) {
return res.status(403).json({ message: 'Token invalid.' });
}
req.user = decoded; // Add user information to the request object
next(); // Proceed to the next middleware/route handler
});
}
Apply this middleware to your protected routes.
6. Token Refresh (Optional)
JWTs have a limited lifespan. Implement token refresh mechanisms to provide users with new tokens without requiring them to log in again frequently.
- Use refresh tokens stored securely on the server.
- When the access token expires, use the refresh token to generate a new access token and (optionally) a new refresh token.
7. Security Considerations
- Secret Key: Keep your secret key extremely secure! Store it in an environment variable or configuration file, not directly in your code.
- Token Expiry: Set appropriate expiry times for tokens to minimize the impact of compromised tokens.
- HTTPS: Always use HTTPS to protect token transmission.
- Storage: Store tokens securely on the client-side (e.g., using HttpOnly cookies).
- cyber security best practices: Regularly review and update your implementation to address potential vulnerabilities.

