OAuth 2.0 и JWT авторизация на JavaScript: на практике
Современные веб-приложения редко обходятся без системы аутентификации и авторизации. Два самых популярных стандарта — OAuth 2.0 и JWT (JSON Web Tokens) — часто используются вместе для создания безопасных и масштабируемых решений. В этой статье мы разберём, как реализовать OAuth 2.0 и JWT авторизацию на JavaScript (Node.js) с практическими примерами кода.
Материал будет полезен как начинающим, так и опытным разработчикам, которые хотят глубже понять механизмы работы токенов и делегированного доступа.
Что такое OAuth 2.0 и JWT?
OAuth 2.0 — это протокол авторизации, который позволяет приложениям получать ограниченный доступ к ресурсам пользователя без передачи его учётных данных. Например, вы можете войти на сайт через Google или GitHub — это и есть OAuth 2.0.
JWT (JSON Web Token) — это компактный формат токена, который содержит закодированные данные (payload) и подпись. JWT используется для передачи информации между сторонами (клиент и сервер) и проверки её подлинности.
В связке OAuth 2.0 выступает как протокол выдачи токенов, а JWT — как формат самих токенов доступа.
Настройка сервера и установка зависимостей
Для начала создадим простой сервер на Express.js и установим необходимые пакеты:
npm init -y
npm install express jsonwebtoken dotenv cors axios
npm install --save-dev nodemon
Структура проекта:
server.js— основной файл сервера.env— переменные окруженияmiddleware/auth.js— middleware для проверки JWTroutes/auth.js— маршруты аутентификации
Реализация JWT-авторизации
Начнём с базовой генерации и проверки JWT-токенов. Создадим server.js:
const express = require('express');
const jwt = require('jsonwebtoken');
require('dotenv').config();
const app = express();
app.use(express.json());
const SECRET_KEY = process.env.JWT_SECRET || 'my_secret_key';
// Генерация токена
function generateToken(user) {
const payload = {
id: user.id,
email: user.email,
role: user.role
};
return jwt.sign(payload, SECRET_KEY, { expiresIn: '1h' });
}
// Пример маршрута для входа
app.post('/login', (req, res) => {
const { email, password } = req.body;
// Здесь должна быть проверка в БД
const user = { id: 1, email, role: 'user' };
const token = generateToken(user);
res.json({ token });
});
// Middleware для проверки токена
function authenticateToken(req, res, next) {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
if (!token) {
return res.status(401).json({ error: 'Токен не предоставлен' });
}
jwt.verify(token, SECRET_KEY, (err, user) => {
if (err) {
return res.status(403).json({ error: 'Недействительный токен' });
}
req.user = user;
next();
});
}
// Защищённый маршрут
app.get('/profile', authenticateToken, (req, res) => {
res.json({ message: 'Доступ разрешён', user: req.user });
});
app.listen(3000, () => console.log('Сервер запущен на порту 3000'));
Интеграция OAuth 2.0 через Google
Теперь добавим OAuth 2.0 с использованием Google в качестве провайдера. Создадим routes/auth.js:
const express = require('express');
const axios = require('axios');
const jwt = require('jsonwebtoken');
const router = express.Router();
const GOOGLE_CLIENT_ID = process.env.GOOGLE_CLIENT_ID;
const GOOGLE_CLIENT_SECRET = process.env.GOOGLE_CLIENT_SECRET;
const REDIRECT_URI = 'http://localhost:3000/auth/google/callback';
const JWT_SECRET = process.env.JWT_SECRET;
// Маршрут для начала OAuth
router.get('/google', (req, res) => {
const url = `https://accounts.google.com/o/oauth2/v2/auth?client_id=${GOOGLE_CLIENT_ID}&redirect_uri=${REDIRECT_URI}&response_type=code&scope=email profile`;
res.redirect(url);
});
// Callback после авторизации
router.get('/google/callback', async (req, res) => {
const { code } = req.query;
try {
// Обмен кода на токен доступа
const tokenResponse = await axios.post('https://oauth2.googleapis.com/token', {
code,
client_id: GOOGLE_CLIENT_ID,
client_secret: GOOGLE_CLIENT_SECRET,
redirect_uri: REDIRECT_URI,
grant_type: 'authorization_code'
});
const accessToken = tokenResponse.data.access_token;
// Получение данных пользователя
const userResponse = await axios.get('https://www.googleapis.com/oauth2/v2/userinfo', {
headers: { Authorization: `Bearer ${accessToken}` }
});
const user = userResponse.data;
// Генерация JWT для нашего приложения
const jwtPayload = {
id: user.id,
email: user.email,
name: user.name,
picture: user.picture
};
const jwtToken = jwt.sign(jwtPayload, JWT_SECRET, { expiresIn: '24h' });
res.json({
message: 'Успешная авторизация через Google',
token: jwtToken,
user: jwtPayload
});
} catch (error) {
console.error('Ошибка OAuth:', error);
res.status(500).json({ error: 'Ошибка авторизации' });
}
});
module.exports = router;
В server.js добавляем использование этого роутера:
const authRoutes = require('./routes/auth');
app.use('/auth', authRoutes);
Middleware для проверки ролей и прав доступа
Часто требуется ограничить доступ к определённым маршрутам в зависимости от роли пользователя. Создадим middleware checkRole:
// middleware/checkRole.js
function checkRole(...allowedRoles) {
return (req, res, next) => {
if (!req.user) {
return res.status(401).json({ error: 'Не авторизован' });
}
const userRole = req.user.role;
if (!allowedRoles.includes(userRole)) {
return res.status(403).json({ error: 'Недостаточно прав' });
}
next();
};
}
module.exports = checkRole;
Пример использования в маршрутах:
Блоги
Рекомендаций по книгам
Читайте также
Рефакторинг TypeScript кода: когда и как превратить хаос в порядок
Property has no initializer в TypeScript: как исправить за 5 минут
Работа с файловой системой в Swift: Полное руководство
Go в 2025 году: обзор новинок и возможностей языка
Интернационализация PHP: как сделать сайт на всех языках мира