PurpleSchool — курсы программирования онлайн
  • Пути
    • Frontend React разработчик
    • Frontend Vue разработчик
    • Backend разработчик Node.js
    • Fullstack разработчик React / Node.js
    • Mobile разработчик React Native
    • Backend разработчик Golang
    • Devops инженер
    • Backend разработчик Python
  • AI для кодаНовое
  • О нас
    • Отзывы
    • Реферальная программа
    • О компании
    • Контакты
  • Иконка открытия меню
    • Сообщество
    • PurpleПлюс
    • AI Собеседование
    • AI тренажёр
    • Проекты
PurpleSchool — платформа бесплатных roadmap и курсов для разработчиков
ютуб иконка
Telegram иконка
VK иконка
VK иконка
Курсы
ГлавнаяКаталог курсовFrontendBackendFullstack
Практика
КарьераПроектыPurpleПлюс
Материалы
БлогБаза знаний
Документы
Договор офертаПолитика конфиденциальностиПроверка сертификатаМиграция курсовРеферальная программа
Реквизиты
ИП Ларичев Антон АндреевичИНН 773373765379contact@purpleschool.ru

PurpleSchool © 2020 -2026 Все права защищены

  • Курсы
    • FrontendИконка стрелки
    • AI разработкаИконка стрелки
    • BackendИконка стрелки
    • DevOpsИконка стрелки
    • MobileИконка стрелки
    • ТестированиеИконка стрелки
    • Soft-skillsИконка стрелки
    • ДизайнИконка стрелки
    Иконка слояПерейти в каталог курсов
  • Бесплатно
    • Курсы
    • JavaScript Основы разработкиPython Основы PythonCSS CSS FlexboxКарта развития
    • База знанийИконка стрелки
    • Новостные рассылкиИконка стрелки
  • PurpleSchool — курсы программирования онлайн
    • AI для кодаНовое
    • Сообщество
    • PurpleПлюс
    • AI Собеседование
    • AI тренажёр
    • Проекты
    Главная
    Сообщество
    Авторизация и аутентификация в Node.js: JWT, OAuth2 и сессии

    Авторизация и аутентификация в Node.js: JWT, OAuth2 и сессии

    Аватар автора Авторизация и аутентификация в Node.js: JWT, OAuth2 и сессии

    Антон Ларичев

    Иконка календаря11 июня 2026
    Node.jsБезопасностьJWTOAuth2АутентификацияmiddleИконка уровня middle
    Картинка поста Авторизация и аутентификация в Node.js: JWT, OAuth2 и сессии

    Введение

    Аутентификация отвечает на вопрос «кто вы?», а авторизация — «что вам разрешено?». Эти два слоя часто путают, но проектируются они по-разному: первый проверяет подлинность пользователя, второй — его права. В Node.js для решения этих задач исторически сложились три подхода: серверные сессии, JWT и делегированная авторизация через OAuth2. Каждый имеет свою область применимости, и выбор зависит от модели угроз, архитектуры и удобства эксплуатации.

    В статье разберём, как реализовать каждый подход на Express, где у них слабые места и как их комбинировать. Примеры намеренно минималистичные — чтобы сосредоточиться на сути, а не на обвязке.

    Серверные сессии

    Классическая схема: сервер хранит состояние сессии (в Redis, БД или памяти), а клиенту отдаёт только идентификатор в HttpOnly-куке. Это безопасно по умолчанию: JS на клиенте к куке не достучится, отзыв сессии — это просто удаление записи в хранилище.

    import express from 'express';
    import session from 'express-session';
    import RedisStore from 'connect-redis';
    import { createClient } from 'redis';
    
    const redisClient = createClient({ url: process.env.REDIS_URL });
    await redisClient.connect();
    
    const app = express();
    app.use(express.json());
    
    app.use(session({
      store: new RedisStore({ client: redisClient }),
      secret: process.env.SESSION_SECRET,
      resave: false,
      saveUninitialized: false,
      cookie: {
        httpOnly: true,        // недоступна из JS
        secure: true,          // только по HTTPS
        sameSite: 'lax',       // защита от большинства CSRF
        maxAge: 1000 * 60 * 60 * 24 // сутки
      }
    }));
    
    app.post('/login', async (req, res) => {
      const user = await verifyCredentials(req.body.email, req.body.password);
      if (!user) return res.status(401).end();
      // сохраняем минимум данных — остальное подтянем из БД
      req.session.userId = user.id;
      res.json({ ok: true });
    });
    

    Плюсы: моментальный отзыв доступа, простая ротация, состояние всегда актуально. Минусы: нужна общая для всех инстансов сессионная БД, требуется CSRF-защита для небезопасных методов.

    JWT: токены без состояния

    JWT (JSON Web Token) — это подписанный токен, который сам содержит данные о пользователе. Сервер не хранит сессию: достаточно проверить подпись и срок действия. Удобно для распределённых API и микросервисов.

    import jwt from 'jsonwebtoken';
    
    const ACCESS_TTL = '15m';
    const REFRESH_TTL = '30d';
    
    function issueTokens(user) {
      const access = jwt.sign(
        { sub: user.id, role: user.role },
        process.env.JWT_ACCESS_SECRET,
        { expiresIn: ACCESS_TTL }
      );
      const refresh = jwt.sign(
        { sub: user.id, jti: crypto.randomUUID() },
        process.env.JWT_REFRESH_SECRET,
        { expiresIn: REFRESH_TTL }
      );
      return { access, refresh };
    }
    
    // middleware для защищённых маршрутов
    function authRequired(req, res, next) {
      const header = req.headers.authorization ?? '';
      const token = header.startsWith('Bearer ') ? header.slice(7) : null;
      if (!token) return res.status(401).end();
      try {
        req.user = jwt.verify(token, process.env.JWT_ACCESS_SECRET);
        next();
      } catch {
        res.status(401).end();
      }
    }
    

    Главное правило — короткоживущий access-токен и отдельный refresh с возможностью отзыва. Refresh-токен лучше хранить в HttpOnly-куке и записывать его jti в БД, чтобы можно было инвалидировать конкретное устройство.

    Где хранить токены на клиенте

    Хранение JWT в localStorage — частый источник XSS-уязвимостей: любой инжектированный скрипт получит доступ к токену. Безопаснее держать access-токен в памяти JS-процесса, а refresh — в HttpOnly-куке с SameSite=Strict или Lax.

    OAuth2: делегированная авторизация

    OAuth2 нужен, когда вы хотите войти через GitHub, Google или Yandex, либо предоставить сторонним приложениям ограниченный доступ к вашему API. Это протокол получения access-токена от имени пользователя без передачи его пароля.

    Для веб-приложений подходит Authorization Code Flow с PKCE. Удобнее всего реализовать его через Passport.js или специализированные библиотеки.

    import passport from 'passport';
    import { Strategy as GitHubStrategy } from 'passport-github2';
    
    passport.use(new GitHubStrategy({
      clientID: process.env.GITHUB_CLIENT_ID,
      clientSecret: process.env.GITHUB_CLIENT_SECRET,
      callbackURL: '/auth/github/callback',
      scope: ['user:email']
    }, async (accessToken, refreshToken, profile, done) => {
      // ищем пользователя или создаём нового
      const user = await upsertUserByOAuth('github', profile);
      done(null, user);
    }));
    
    app.get('/auth/github', passport.authenticate('github'));
    
    app.get('/auth/github/callback',
      passport.authenticate('github', { failureRedirect: '/login' }),
      (req, res) => {
        // после успешного входа создаём свою сессию или JWT
        req.session.userId = req.user.id;
        res.redirect('/');
      }
    );
    

    Обратите внимание: OAuth2 решает только задачу получения токена от провайдера. После колбэка вы всё равно создаёте собственную сессию или выдаёте свой JWT — провайдерский access-токен наружу не пробрасывается.

    Частые ошибки

    • Использование alg: none или слабого секрета для JWT. Подпись HS256 требует длинного случайного ключа, а лучше — пары RS256/ES256.
    • Длинный TTL у access-токена. Если токен живёт сутки, отозвать его без чёрного списка невозможно. Делайте 5–15 минут и обновляйте через refresh.
    • Хранение JWT в localStorage. Любая XSS превращается в кражу токена. Используйте HttpOnly-куки или память процесса.
    • Отсутствие CSRF-защиты для куки-сессий. SameSite=Lax помогает, но для критичных операций добавляйте CSRF-токен.
    • Доверие данным из JWT без проверки подписи. jwt.decode не проверяет подпись — всегда вызывайте jwt.verify.
    • Реализация OAuth2 вручную. Протокол кажется простым, но детали PKCE, state, nonce легко упустить. Берите проверенные библиотеки.
    • Смешение ролей в access-токене без актуализации. Если права пользователя поменялись, старый JWT всё ещё их содержит до истечения срока.

    Заключение

    Сессии, JWT и OAuth2 — не конкуренты, а инструменты с разными зонами ответственности. Для классического веб-приложения с серверным рендерингом сессии в Redis остаются самым простым и безопасным выбором. JWT раскрывают потенциал в распределённых API и мобильных клиентах, особенно в паре с refresh-токенами. OAuth2 нужен там, где требуется делегированный доступ или социальный вход.

    Выбирайте подход осознанно, опираясь на модель угроз и эксплуатационные требования, и не пренебрегайте базовыми мерами: HTTPS, HttpOnly-куки, короткие TTL, проверка подписи и валидация всех входных параметров.

    Иконка глаза4

    Комментарии

    0

    Постройте личный план изучения CSS Flexbox - полный курс и практика его использования до уровня Middle — бесплатно!

    CSS Flexbox - полный курс и практика его использования — часть карты развития Frontend

    • step100+ шагов развития
    • lessons30 бесплатных лекций
    • lessons300 бонусных рублей на счет

    Бесплатные лекции

    Лучшие курсы по теме

    изображение курса

    Основы JavaScript

    Антон Ларичев
    AI-тренажерыAI-тренажеры
    Практика в студииПрактика в студии
    Гарантия
    Бонусы
    иконка звёздочки рейтинга4.8
    3 999 ₽ 6 990 ₽
    Подробнее
    изображение курса

    Продвинутый JavaScript

    Антон Ларичев
    AI-тренажерыAI-тренажеры
    Практика в студииПрактика в студии
    Гарантия
    Бонусы
    иконка звёздочки рейтинга4.8
    3 999 ₽ 6 990 ₽
    Подробнее
    изображение курса

    TypeScript с нуля

    Антон Ларичев
    AI-тренажерыAI-тренажеры
    Практика в студииПрактика в студии
    Гарантия
    Бонусы
    иконка звёздочки рейтинга4.8
    3 999 ₽ 6 990 ₽
    Подробнее

    Похожие статьи

    Картинка поста JWT аутентификация в Node.js: access и refresh токены
    Иконка аватараАнтон
    Иконка календаря27 мая 2026
    Node.jsJWTАутентификация+ 2middleИконка уровня middle

    JWT аутентификация в Node.js: access и refresh токены

    JWT аутентификация в Node.js: разбираем работу access и refresh токенов, генерацию, валидацию и безопасное хранение на практике.

    Иконка чипа0
    Иконка глаза239
    Иконка комментариев0
    Картинка поста WebSocket на Node.js: пишем чат и real-time уведомления
    Иконка аватараАнтон
    Иконка календаря09 июня 2026
    WebSocketNode.jsReal-time+ 1middleИконка уровня middle

    WebSocket на Node.js: пишем чат и real-time уведомления

    WebSocket на Node.js: разбираем протокол, пишем чат на ws-сервере и систему real-time уведомлений с reconnect и heartbeat.

    Иконка чипа+1
    Иконка глаза80
    Иконка комментариев0
    Картинка поста Архитектура Node.js: слои, модули и Dependency Injection
    Иконка аватараАнтон
    Иконка календаря08 июня 2026
    Node.jsАрхитектураBackend+ 1middleИконка уровня middle

    Архитектура Node.js: слои, модули и Dependency Injection

    Архитектура Node.js приложения: разбираем слоистую структуру, разделение на модули и применение Dependency Injection для масштабируемого кода.

    Иконка чипа0
    Иконка глаза125
    Иконка комментариев0
    Иконка чипа0