Як реалізувати автентифікацію JWT в Express.js?
Аутентифікація JWT в Express.js
JWT (JSON Web Token) — це компактний, самодостатній токен, що використовується для безстатевої аутентифікації. Він усуває необхідність у сесіях на стороні сервера.
Як працює JWT
1. Користувач входить в систему (POST /auth/login)
2. Сервер перевіряє облікові дані → генерує JWT
3. Клієнт зберігає JWT (localStorage / httpOnly cookie)
4. Клієнт надсилає JWT у заголовку Authorization для кожного запиту
5. Сервер перевіряє JWT → надає доступСтруктура JWT
eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJBbGljZSJ9.signature
Заголовок Вантаж ПідписНалаштування
bash
npm install jsonwebtoken bcryptjsМаршрут входу (Видача токена)
js
const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');
const JWT_SECRET = process.env.JWT_SECRET; // зберігайте в env!
const JWT_EXPIRES_IN = '7d';
app.post('/auth/login', async (req, res, next) => {
try {
const { email, password } = req.body;
// 1. Знайти користувача
const user = await User.findOne({ email });
if (!user) {
return res.status(401).json({ error: 'Недійсні облікові дані' });
}
// 2. Перевірити пароль
const isValid = await bcrypt.compare(password, user.passwordHash);
if (!isValid) {
return res.status(401).json({ error: 'Недійсні облікові дані' });
}
// 3. Підписати JWT
const token = jwt.sign(
{ id: user.id, email: user.email, role: user.role },
JWT_SECRET,
{ expiresIn: JWT_EXPIRES_IN }
);
res.json({ token, expiresIn: JWT_EXPIRES_IN });
} catch (err) {
next(err);
}
});Middleware для аутентифікації (Перевірка токена)
js
function authenticate(req, res, next) {
const authHeader = req.headers.authorization;
if (!authHeader?.startsWith('Bearer ')) {
return res.status(401).json({ error: 'Токен не надано' });
}
const token = authHeader.split(' ')[1];
try {
const decoded = jwt.verify(token, JWT_SECRET);
req.user = decoded; // { id, email, role, iat, exp }
next();
} catch (err) {
if (err.name === 'TokenExpiredError') {
return res.status(401).json({ error: 'Токен прострочений' });
}
return res.status(401).json({ error: 'Недійсний токен' });
}
}
// Авторизація на основі ролей
function authorize(...roles) {
return (req, res, next) => {
if (!roles.includes(req.user.role)) {
return res.status(403).json({ error: 'Заборонено' });
}
next();
};
}Захищені маршрути
js
// Будь-який аутентифікований користувач
app.get('/profile', authenticate, (req, res) => {
res.json({ user: req.user });
});
// Тільки адміністратори
app.delete('/users/:id', authenticate, authorize('admin'), async (req, res) => {
await User.deleteById(req.params.id);
res.status(204).send();
});Реєстрація з хешуванням пароля
js
app.post('/auth/register', async (req, res, next) => {
try {
const { email, password } = req.body;
const exists = await User.findOne({ email });
if (exists) return res.status(409).json({ error: 'Email вже зайнято' });
const passwordHash = await bcrypt.hash(password, 12); // 12 раундів солі
const user = await User.create({ email, passwordHash });
res.status(201).json({ id: user.id, email: user.email });
} catch (err) {
next(err);
}
});Шаблон для токенів оновлення
js
// Токен доступу: короткочасний (15хв)
const accessToken = jwt.sign(payload, JWT_SECRET, { expiresIn: '15m' });
// Токен оновлення: довгостроковий (7д), зберігається в httpOnly cookie
const refreshToken = jwt.sign(payload, REFRESH_SECRET, { expiresIn: '7d' });
res.cookie('refreshToken', refreshToken, {
httpOnly: true, // недоступний через JS
secure: true, // тільки HTTPS
sameSite: 'strict',
maxAge: 7 * 24 * 60 * 60 * 1000 // 7 днів
});Підсумок
Аутентифікація JWT в Express включає:
- Маршрут входу → перевірка облікових даних → підписати JWT
- Middleware для аутентифікації → перевірка JWT → прикріпити користувача до
req - Захищені маршрути → використання middleware
authenticate - Авторизація → перевірка ролей після аутентифікації
Завжди зберігайте секрет JWT у змінних середовища та використовуйте короткі терміни дії з токенами оновлення в продуктивному середовищі.
Коротка відповідь
Для співбесідиPremium
Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.