Валидация токенов доступа

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

Токены доступа могут иметь различную природу и формат в зависимости от архитектуры системы:

  • JWT (JSON Web Token) — структурированные токены, состоящие из трёх частей: заголовка, полезной нагрузки и подписи.
  • API Key — упрощённые строки фиксированной или переменной длины.
  • OAuth Access Token — произвольные строки, выдаваемые авторизационным сервером.

Несмотря на различия, все токены объединяет необходимость базовой проверки:

  • соответствие формату (строка, допустимые символы)
  • отсутствие пустых значений
  • соответствие длине
  • проверка на наличие запрещённых символов
  • при необходимости — соответствие шаблону (regex)

Для этих задач часто используется библиотека validator.js, предоставляющая набор функций для проверки строковых значений.


Базовая валидация токена как строки

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

import validator from "validator";

function isValidToken(token) {
  return typeof token === "string" && !validator.isEmpty(token);
}

Функция validator.isEmpty() позволяет исключить пустые строки, включая строки из пробелов при дополнительной нормализации.


Проверка длины токена

Многие системы используют ограничения на длину токена для защиты от атак и ошибок передачи данных:

function isValidTokenLength(token) {
  return validator.isLength(token, { min: 16, max: 512 });
}

Такая проверка особенно актуальна для API ключей и session token, где фиксированная длина часто является частью протокола.


Ограничение допустимых символов

Токены доступа обычно ограничены безопасным набором символов (Base64, hex или URL-safe формат). Для этого используется регулярная проверка:

function isValidTokenCharset(token) {
  const pattern = /^[A-Za-z0-9\-_.]+$/;
  return validator.matches(token, pattern);
}

Метод validator.matches() обеспечивает унифицированную проверку строк по регулярному выражению, снижая вероятность ошибок ручной работы с RegExp.


Валидация JWT-токена

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

function isJwtFormat(token) {
  const jwtPattern = /^[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+$/;
  return validator.matches(token, jwtPattern);
}

Такая проверка не подтверждает подлинность токена, но исключает явно некорректные значения.

Дополнительная проверка может включать разбиение строки:

function isJwtStructureValid(token) {
  const parts = token.split(".");
  return parts.length === 3 && parts.every(part => part.length > 0);
}

Валидация OAuth и API ключей

API ключи часто представляют собой строки фиксированного формата, иногда с префиксом:

function isApiKeyValid(token) {
  return validator.isLength(token, { min: 20, max: 80 }) &&
         validator.isAlphanumeric(token, "en-US");
}

При наличии префикса (например, sk_ или api_) добавляется дополнительная проверка:

function isPrefixedApiKey(token) {
  return validator.matches(token, /^(sk_|api_)[A-Za-z0-9]+$/);
}

Нормализация токенов перед проверкой

Перед валидацией токены часто требуют предварительной обработки:

  • удаление пробелов
  • приведение к единому регистру (если допустимо)
  • очистка управляющих символов
function normalizeToken(token) {
  return validator.trim(token);
}

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


Кастомные валидаторы для токенов

Стандартных функций часто недостаточно, особенно в корпоративных системах. Validator.js позволяет комбинировать проверки:

function validateAccessToken(token) {
  return (
    typeof token === "string" &&
    validator.isLength(token, { min: 20, max: 512 }) &&
    validator.matches(token, /^[A-Za-z0-9\-_.]+$/)
  );
}

Для более сложной логики можно создавать многоступенчатую проверку:

function validateTokenAdvanced(token) {
  if (!token || typeof token !== "string") return false;
  if (!validator.isLength(token, { min: 20 })) return false;
  if (validator.contains(token, " ")) return false;
  return validator.matches(token, /^[A-Za-z0-9\-_.]+$/);
}

Обработка ошибок валидации

При интеграции валидации токенов в API важно возвращать диагностируемые ошибки:

function validateTokenWithReason(token) {
  if (!token) return { valid: false, reason: "empty_token" };
  if (!validator.isLength(token, { min: 20 })) {
    return { valid: false, reason: "invalid_length" };
  }
  if (!validator.matches(token, /^[A-Za-z0-9\-_.]+$/)) {
    return { valid: false, reason: "invalid_charset" };
  }
  return { valid: true };
}

Такой подход упрощает отладку и логирование инцидентов безопасности.


Ограничения клиентской валидации

Валидация токенов на стороне клиента носит исключительно предварительный характер. Даже корректно сформированный токен:

  • может быть просрочен
  • может быть отозван сервером
  • может не соответствовать правам доступа

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


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

В реальных приложениях Validator.js часто используется совместно с:

  • библиотеками декодирования JWT
  • middleware авторизации (Express, Koa)
  • системами управления сессиями

Пример интеграции в middleware:

function authMiddleware(req, res, next) {
  const token = req.headers.authorization;

  if (!validator.isLength(token || "", { min: 20 })) {
    return res.status(401).send("Invalid token");
  }

  next();
}

Типовые ошибки при валидации токенов

При использовании строковой валидации часто встречаются следующие ошибки:

  • проверка только на непустую строку без проверки формата
  • отсутствие ограничения длины
  • использование слишком строгих regex, ломающих валидные токены
  • попытка «нормализовать» токен изменением регистра
  • игнорирование пробелов и скрытых символов

Каждая из этих ошибок снижает надёжность системы авторизации и может приводить к уязвимостям или ложным отказам доступа.