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

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

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

Начать курс

Авторизация и аутентификация в Node.js: Полное руководство

В современной веб-разработке безопасность пользовательских данных — приоритет номер один. В этом руководстве мы разберём ключевые инструменты и библиотеки для реализации аутентификации (проверки подлинности пользователя) и авторизации (проверки прав доступа) в приложениях на Node.js. Вы узнаете, как настроить защиту маршрутов, хешировать пароли и работать с токенами доступа.

1. Основные понятия

  • Аутентификация — процесс проверки, является ли пользователь тем, за кого себя выдаёт (обычно через логин и пароль).
  • Авторизация — определение, какие ресурсы и действия доступны аутентифицированному пользователю.
  • JWT (JSON Web Token) — компактный и самодостаточный способ передачи данных в виде JSON-объекта. Используется для создания токенов доступа.
  • Сессии — традиционный метод хранения данных о пользователе на сервере (обычно с использованием express-session).

2. Ключевые библиотеки для Node.js

2.1. bcrypt — хеширование паролей

Никогда не храните пароли в открытом виде. bcrypt — это библиотека для безопасного хеширования с использованием соли.

const bcrypt = require('bcrypt');
const saltRounds = 10;

// Хеширование пароля
async function hashPassword(password) {
  const salt = await bcrypt.genSalt(saltRounds);
  const hash = await bcrypt.hash(password, salt);
  return hash;
}

// Проверка пароля
async function checkPassword(password, hash) {
  const match = await bcrypt.compare(password, hash);
  return match; // true или false
}

2.2. jsonwebtoken — работа с JWT

Библиотека jsonwebtoken позволяет создавать и проверять JWT-токены. Токены обычно состоят из заголовка, полезной нагрузки (payload) и подписи.

const jwt = require('jsonwebtoken');
const secretKey = 'ваш-секретный-ключ';

// Создание токена
function generateToken(userId, role) {
  const payload = { userId, role };
  const token = jwt.sign(payload, secretKey, { expiresIn: '1h' });
  return token;
}

// Проверка токена (middleware)
function verifyToken(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, secretKey, (err, decoded) => {
    if (err) return res.status(403).json({ error: 'Недействительный токен' });
    req.user = decoded;
    next();
  });
}

2.3. Passport.js — универсальная аутентификация

Passport.js — это middleware для Express, поддерживающий более 500 стратегий (локальная, OAuth, JWT, Google, Facebook и др.). Пример локальной стратегии:

const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const User = require('./models/User');

passport.use(new LocalStrategy(
  async (username, password, done) => {
    try {
      const user = await User.findOne({ username });
      if (!user) return done(null, false, { message: 'Пользователь не найден' });
      
      const isValid = await bcrypt.compare(password, user.password);
      if (!isValid) return done(null, false, { message: 'Неверный пароль' });
      
      return done(null, user);
    } catch (err) {
      return done(err);
    }
  }
));

// Сериализация и десериализация (для сессий)
passport.serializeUser((user, done) => done(null, user.id));
passport.deserializeUser(async (id, done) => {
  const user = await User.findById(id);
  done(null, user);
});

3. Полный пример: регистрация и вход

Соберём всё вместе в простом Express-приложении.

const express = require('express');
const session = require('express-session');
const passport = require('passport');
const bcrypt = require('bcrypt');
const User = require('./models/User'); // модель Mongoose

const app = express();
app.use(express.json());
app.use(session({ secret: 'секрет', resave: false, saveUninitialized: false }));
app.use(passport.initialize());
app.use(passport.session());

// Регистрация
app.post('/register', async (req, res) => {
  try {
    const { username, password } = req.body;
    const hashedPassword = await bcrypt.hash(password, 10);
    const user = new User({ username, password: hashedPassword });
    await user.save();
    res.status(201).json({ message: 'Пользователь создан' });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

// Вход (лок                    

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