Implementing JWT-Based Authentication in Node.js
JWT (JSON Web Token) is a popular method for authenticating users in web applications. It’s a secure and efficient way to transmit information between parties as a JSON object. Here’s a basic breakdown of how to implement JWT-based authentication in a Node.js application:
1. Install Required Packages:
npm install jsonwebtoken bcryptjs express-jwt
- jsonwebtoken: Used to sign and verify JWTs.
- bcryptjs: Used for password hashing.
- express-jwt: Used to protect routes with JWT authentication.
2. Set Up Express Server:
const express = require('express');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');
const expressJwt = require('express-jwt');
const app = express();
const port = 3000;
// ... other middleware and routes
3. Create a User Model:
const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
username: { type: String, required: true, unique: true },
password: { type: String, required: true },
});
userSchema.methods.generateJWT = function() {
const token = jwt.sign({
id: this._id,
username: this.username
}, process.env.JWT_SECRET, { expiresIn: '1h' });
return token;
};
module.exports = mongoose.model('User', userSchema);
4. Implement User Registration and Login:
// Register a new user
app.post('/register', async (req, res) => {
const { username, password } = req.body;
try {
const hashedPassword = await bcrypt.hash(password, 10);
const user = new User({ username, password: hashedPassword });
await user.save();
res.status(201).json({ message: 'User registered successfully' });
} catch (err) {
res.status(500).json({ error: err.message });
}
});
// Login a user
app.post('/login', async (req, res) => {
const { username, password } = req.body;
try {
const user = await User.findOne({ username });
if (!user) {
return res.status(401).json({ error: 'Invalid credentials' });
}
const passwordMatch = await bcrypt.compare(password, user.password);
if (!passwordMatch) {
return res.status(401).json({ error: 'Invalid credentials' });
}
const token = user.generateJWT();
res.json({ token });
} catch (err) {
res.status(500).json({ error: err.message });
}
});
5. Protect Routes with JWT:
app.use(expressJwt({ secret: process.env.JWT_SECRET, algorithms: ['HS256'] }).unless({ path: ['/login', '/register'] }));
// Protected route
app.get('/protected', (req, res) => {
res.json({ message: 'Protected route accessed' });
});
Key Points:
- Secret Key: Keep our JWT secret key secure.
- Token Expiration: Set an appropriate expiration time for our tokens.
- Refresh Tokens: Consider using refresh tokens for long-lived sessions.
- Secure Storage: Store JWTs securely on the client-side (e.g., in
localStorage
orsessionStorage
). - HTTP-Only Cookies: For additional security, consider using HTTP-only cookies to store JWTs.
- Error Handling: Implement robust error handling to prevent unauthorized access.
By following these steps and considering security best practices, we can effectively implement JWT-based authentication in our Node.js application.