Авторизация и аутентификация в TypeScript: полное руководство

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

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

Начать курс

Авторизация и аутентификация в TypeScript: полное руководство

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

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

Прежде чем перейти к коду, важно различать два термина:

  • Аутентификация (Authentication) — проверка подлинности пользователя (кто вы?). Обычно выполняется через логин/пароль, токены или биометрию.
  • Авторизация (Authorization) — определение прав доступа (что вам можно делать?). Например, доступ к админ-панели только для роли "admin".

Популярные библиотеки для TypeScript

В экосистеме TypeScript/Node.js существует несколько проверенных решений:

  • Passport.js — самая популярная библиотека для стратегий аутентификации (local, JWT, OAuth). Имеет отличную поддержку TypeScript через типы @types/passport.
  • jsonwebtoken — работа с JWT (JSON Web Tokens). Полностью типизирована.
  • bcrypt — хеширование паролей. Используется вместе с другими библиотеками.
  • express-session — управление сессиями на сервере.

Пример 1: Базовая аутентификация с JWT

Рассмотрим создание простой системы с токенами доступа. Установите зависимости:

npm install express jsonwebtoken bcrypt @types/express @types/jsonwebtoken @types/bcrypt

Создадим сервер с регистрацией и логином:

import express, { Request, Response } from 'express';
import jwt from 'jsonwebtoken';
import bcrypt from 'bcrypt';

const app = express();
app.use(express.json());

const SECRET_KEY = 'your-secret-key';
const users: { username: string; passwordHash: string }[] = [];

// Регистрация
app.post('/register', async (req: Request, res: Response) => {
  const { username, password } = req.body;
  const passwordHash = await bcrypt.hash(password, 10);
  users.push({ username, passwordHash });
  res.status(201).json({ message: 'User created' });
});

// Логин
app.post('/login', async (req: Request, res: Response) => {
  const { username, password } = req.body;
  const user = users.find(u => u.username === username);
  if (!user) return res.status(401).json({ error: 'Invalid credentials' });

  const isValid = await bcrypt.compare(password, user.passwordHash);
  if (!isValid) return res.status(401).json({ error: 'Invalid credentials' });

  const token = jwt.sign({ username }, SECRET_KEY, { expiresIn: '1h' });
  res.json({ token });
});

// Защищенный маршрут
app.get('/protected', (req: Request, res: Response) => {
  const authHeader = req.headers.authorization;
  if (!authHeader) return res.status(401).json({ error: 'No token provided' });

  const token = authHeader.split(' ')[1]; // Bearer token
  try {
    const decoded = jwt.verify(token, SECRET_KEY);
    res.json({ message: 'Access granted', user: decoded });
  } catch {
    res.status(403).json({ error: 'Invalid token' });
  }
});

app.listen(3000, () => console.log('Server running on port 3000'));

Пример 2: Middleware для авторизации с ролями

Добавим ролевую модель. Создадим типизированное middleware:

interface JwtPayload {
  username: string;
  role: 'user' | 'admin';
}

// Middleware для проверки аутентификации
function authenticate(req: Request, res: Response, next: Function) {
  const token = req.headers.authorization?.split(' ')[1];
  if (!token) return res.status(401).json({ error: 'Unauthorized' });

  try {
    const decoded = jwt.verify(token, SECRET_KEY) as JwtPayload;
    (req as any).user = decoded;
    next();
  } catch {
    res.status(403).json({ error: 'Forbidden' });
  }
}

// Middleware для проверки роли
function authorize(...roles: string[]) {
  return (req: Request, res: Response, next: Function) => {
    const user = (req as any).user as JwtPayload;
    if (!roles.includes(user.role)) {
      return res.status(403).json({ error: 'Insufficient permissions' });
    }
    next();
  };
}

// Использование
app.get('/admin', authenticate, authorize('admin'), (req, res) => {
  res.json({ message: 'Admin panel' });
});

Пример 3: Аутентификация через OAuth 2.0 (Google)

Для реализации "Войти через Google" используем Passport.js:

npm install passport passport-google-oauth20 @types/passport @types/passport-google-oauth20
import passport from 'passport';
import { Strategy as                    

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