OAuth 2.0 и JWT авторизация на JavaScript: полное руководство

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

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 для проверки JWT
  • routes/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;

Пример использования в маршрутах:



                
                

Блоги

Рекомендаций по книгам