JWT токены в TypeScript: полное руководство по работе с JSON Web Tokens

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

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

Начать курс

JWT токены в TypeScript: полное руководство

JSON Web Token (JWT) — это открытый стандарт (RFC 7519) для создания токенов доступа, основанных на формате JSON. JWT широко используется для аутентификации и обмена информацией между клиентом и сервером. В этой статье мы подробно разберем, как работать с JWT токенами в TypeScript, используя популярные библиотеки и лучшие практики.

Что такое JWT?

JWT состоит из трех частей, разделенных точками:

  • Header (заголовок) — содержит информацию о типе токена и алгоритме подписи
  • Payload (полезная нагрузка) — содержит данные (claims), такие как ID пользователя, роль, срок действия
  • Signature (подпись) — создается из заголовка, payload и секретного ключа

Типичный JWT выглядит так:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Установка библиотек для работы с JWT в TypeScript

Для работы с JWT в TypeScript мы будем использовать библиотеку jsonwebtoken вместе с типами @types/jsonwebtoken.

npm install jsonwebtoken
npm install --save-dev @types/jsonwebtoken

Создание JWT токена в TypeScript

Рассмотрим пример создания JWT токена с типизированным payload:

import jwt from 'jsonwebtoken';

// Определяем интерфейс для payload
interface TokenPayload {
    userId: string;
    email: string;
    role: 'user' | 'admin';
}

// Секретный ключ (в реальном проекте храните в .env)
const JWT_SECRET = 'your-super-secret-key';

// Создаем токен
function generateToken(payload: TokenPayload): string {
    return jwt.sign(payload, JWT_SECRET, {
        expiresIn: '1h', // токен действителен 1 час
        issuer: 'pythonlib.ru',
        subject: payload.userId
    });
}

// Пример использования
const userPayload: TokenPayload = {
    userId: '12345',
    email: 'user@example.com',
    role: 'user'
};

const token = generateToken(userPayload);
console.log('Сгенерированный токен:', token);

Верификация и декодирование JWT

Для проверки подлинности токена и извлечения данных используйте следующий код:

import jwt, { JwtPayload, VerifyErrors } from 'jsonwebtoken';

interface DecodedToken extends JwtPayload {
    userId: string;
    email: string;
    role: 'user' | 'admin';
}

function verifyToken(token: string): DecodedToken | null {
    try {
        const decoded = jwt.verify(token, JWT_SECRET) as DecodedToken;
        return decoded;
    } catch (error) {
        if (error instanceof jwt.TokenExpiredError) {
            console.error('Токен истек');
        } else if (error instanceof jwt.JsonWebTokenError) {
            console.error('Неверный токен');
        } else {
            console.error('Ошибка верификации:', error);
        }
        return null;
    }
}

// Проверяем токен
const decoded = verifyToken(token);
if (decoded) {
    console.log('Данные токена:', decoded);
    console.log('Роль пользователя:', decoded.role);
}

Middleware для Express.js с TypeScript

Интегрируем JWT проверку в Express middleware с полной типизацией:

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

// Расширяем интерфейс Request для хранения данных пользователя
interface AuthRequest extends Request {
    user?: {
        userId: string;
        email: string;
        role: 'user' | 'admin';
    };
}

function authMiddleware(req: AuthRequest, res: Response, next: NextFunction): void {
    const authHeader = req.headers.authorization;

    if (!authHeader || !authHeader.startsWith('Bearer ')) {
        res.status(401).json({ message: 'Токен не предоставлен' });
        return;
    }

    const token = authHeader.split(' ')[1];

    try {
        const decoded = jwt.verify(token, JWT_SECRET) as {
            userId: string;
            email: string;
            role: 'user' | 'admin';
        };

        req.user = decoded;
        next();
    } catch (error) {
        if (error instanceof jwt.TokenExpiredError) {
            res.status(401).json({ message: 'Токен истек' });
        } else {
            res.status(403).json({ message: 'Недействительный токен' });
        }
    }
}

// Пример использования в роуте
app.get('/profile', authMiddleware, (req: AuthRequest, res: Response) => {
    res.json({
        message: 'Доступ разрешен',
        user: req.user
    });
});

Б

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