@IsJWT

Декоратор @IsJWT используется в библиотеке class-validator для проверки того, что строковое значение соответствует формату JSON Web Token (JWT). Он применяется в DTO-классах и обеспечивает валидацию структуры токена без необходимости вручную писать регулярные выражения или разбирать строку.

JWT представляет собой компактный токен, состоящий из трёх частей: заголовка, полезной нагрузки и подписи, закодированных в Base64URL и разделённых точками. Типичный формат выглядит так:

xxxxx.yyyyy.zzzzz

Каждая часть обязана присутствовать, иначе строка не считается валидным JWT.


Структура JWT и требования к формату

JWT всегда состоит из трёх сегментов:

  1. Header (заголовок) — содержит метаданные, например алгоритм подписи.
  2. Payload (данные) — полезная нагрузка с утверждениями (claims).
  3. Signature (подпись) — криптографическая подпись.

Формат:

base64url(header).base64url(payload).base64url(signature)

Ключевое правило: наличие ровно двух точек-разделителей.


Поведение @IsJWT

Декоратор проверяет:

  • строковый тип значения
  • наличие ровно двух точек
  • допустимые символы Base64URL в каждой части
  • отсутствие пустых сегментов

Пример внутренней логики проверки можно представить как эквивалент регулярного выражения:

/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/

Однако реальная реализация более строгая и учитывает особенности формата Base64URL.


Базовое использование

Применение в DTO-классе:

import { IsJWT } from 'class-validator';

export class AuthDto {
  @IsJWT()
  token: string;
}

В этом случае любое значение token, не соответствующее структуре JWT, будет отклонено валидатором.


Интеграция с NestJS

В типичном серверном приложении на NestJS @IsJWT используется внутри DTO, который затем проверяется через ValidationPipe.

import { Body, Controller, Post } from '@nestjs/common';
import { IsJWT } from 'class-validator';

class LoginDto {
  @IsJWT()
  accessToken: string;
}

@Controller('auth')
export class AuthController {
  @Post('verify')
  verify(@Body() dto: LoginDto) {
    return { valid: true };
  }
}

При передаче некорректного токена NestJS автоматически вернёт ошибку валидации.


Отличие от ручной проверки

Без @IsJWT часто используют:

import { Matches } from 'class-validator';

@Matches(/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/)
token: string;

Проблемы такого подхода:

  • отсутствие семантической ясности
  • сложность поддержки регулярного выражения
  • риск ошибок в паттерне
  • отсутствие учёта специфики Base64URL

@IsJWT решает эти проблемы, предоставляя специализированную проверку.


Ограничения валидации

Важно понимать, что @IsJWT проверяет только формат строки, но не её содержимое:

  • не проверяется подпись токена
  • не проверяется срок действия (exp)
  • не декодируется payload
  • не выполняется криптографическая проверка

То есть валидатор подтверждает лишь структурную корректность, а не подлинность токена.


Частые ошибки использования

Передача объекта вместо строки

@IsJWT()
token: object;

Такое значение всегда будет невалидным, так как ожидается строка.


Использование уже декодированного JWT

const decoded = jwt.decode(token);

dto.token = decoded;

После декодирования структура перестаёт быть строкой JWT, что делает проверку @IsJWT неприменимой.


Попытка валидации Bearer-префикса

Authorization: Bearer xxxxx.yyyyy.zzzzz

Если передать всю строку целиком, проверка провалится. @IsJWT не поддерживает префиксы и должен применяться только к чистому токену.


Комбинирование с другими валидаторами

На практике @IsJWT часто используется вместе с ограничением типа:

import { IsJWT, IsString } from 'class-validator';

class TokenDto {
  @IsString()
  @IsJWT()
  token: string;
}

Порядок декораторов не влияет на результат, но помогает явно задать ожидания к данным.


Поведение при пустых значениях

@IsJWT не допускает:

  • пустую строку ""
  • null
  • undefined

Если требуется разрешить отсутствие значения, используется:

import { IsOptional, IsJWT } from 'class-validator';

class TokenDto {
  @IsOptional()
  @IsJWT()
  token?: string;
}

Валидация в массиве

При работе с массивами токенов:

import { IsArray, IsJWT } from 'class-validator';

class BatchDto {
  @IsArray()
  @IsJWT({ each: true })
  tokens: string[];
}

Параметр each: true заставляет валидатор проверять каждый элемент массива отдельно.


Внутренние особенности реализации

class-validator использует функцию-проверку, которая:

  • проверяет тип значения через typeof
  • выполняет разбиение строки по точке
  • проверяет количество сегментов
  • валидирует каждый сегмент как Base64URL
  • отклоняет значения с недопустимыми символами

Сложность проверки остаётся линейной относительно длины строки.


Сравнение с другими подходами

Метод Уровень абстракции Поддерживаемость Семантика
@IsJWT высокий высокая явная
@Matches(regex) средний средняя неочевидная
ручная функция низкий зависит от реализации произвольная

Использование в системах аутентификации

В DTO, связанных с авторизацией, @IsJWT часто применяется для:

  • проверки access token
  • проверки refresh token
  • передачи токенов между микросервисами
  • валидации webhook-запросов

Типичный сценарий:

class RefreshDto {
  @IsJWT()
  refreshToken: string;
}

Поведение при международных и нестандартных токенах

JWT всегда использует Base64URL и ASCII-совместимые символы, поэтому:

  • Unicode-строки недопустимы
  • пробелы недопустимы
  • любые нестандартные кодировки приводят к ошибке

Практическая значимость

Использование @IsJWT позволяет стандартизировать входные данные на уровне DTO и разгрузить бизнес-логику от предварительных проверок структуры токена. Это особенно важно в распределённых системах, где токены передаются между сервисами и точность формата критична для дальнейшей обработки.