Токены доступа используются как основной механизм аутентификации и авторизации в современных веб-приложениях. Они представляют собой строковые значения, которые выдаются сервером после успешной идентификации пользователя и передаются в последующих запросах для подтверждения прав доступа. При работе с такими значениями ключевым этапом становится их валидация на стороне клиента и сервера.
Токены доступа могут иметь различную природу и формат в зависимости от архитектуры системы:
Несмотря на различия, все токены объединяет необходимость базовой проверки:
Для этих задач часто используется библиотека 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 представляет собой три части, разделённые точками. Базовая проверка структуры может быть выполнена без декодирования подписи:
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);
}
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 часто используется совместно с:
Пример интеграции в 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();
}
При использовании строковой валидации часто встречаются следующие ошибки:
Каждая из этих ошибок снижает надёжность системы авторизации и может приводить к уязвимостям или ложным отказам доступа.