При работе с библиотекой @hapi/iron важно понимать, что
сама она не управляет cookie напрямую, а занимается шифрованием
и подписанием данных, которые чаще всего помещаются в cookie.
Поэтому срок жизни cookie определяется на уровне HTTP и логики
приложения, а не самим Iron. Однако именно связка Iron + cookie + токен
формирует единый механизм контроля сессий.
TTL задаёт время жизни данных, после которого они считаются недействительными. В системах с токенами и cookie обычно присутствуют два уровня TTL:
Несоответствие этих значений приводит к типичным ошибкам:
Iron используется для упаковки структуры данных в зашифрованную строку:
При этом библиотека может хранить внутри защищённого payload:
Сам Iron не «знает», что такое TTL, но позволяет включать его в
полезную нагрузку, например как поле exp.
В современных архитектурах TTL токена часто считается главным источником контроля сессии.
Пример структуры данных внутри Iron-сообщения:
{
"userId": 42,
"token": "eyJhbGciOi...",
"exp": 1735689600
}
Поле exp обычно хранит UNIX timestamp окончания жизни
токена.
При каждом запросе происходит:
expЕсли токен истёк — сессия считается недействительной независимо от cookie TTL.
Cookie имеет собственные параметры:
Max-AgeExpiresHttpOnlySecureSameSiteTTL cookie влияет на транспортный уровень:
Однако cookie TTL не гарантирует валидность токена внутри.
Типичная проблема возникает, когда:
Результат:
Обратная ситуация:
Корректная архитектура предполагает единый источник времени жизни:
TTL токена должен определять TTL cookie
Это означает:
const ttl = 15 * 60 * 1000; // 15 минут
const cookieOptions = {
maxAge: ttl,
httpOnly: true,
secure: true,
sameSite: 'lax'
};
const payload = await Iron.seal(
{
userId: 42,
exp: Date.now() + ttl
},
password,
Iron.defaults
);
Ключевой момент — TTL задаётся один раз и используется в двух местах:
TTL токена = TTL cookie
Используется в системах:
Плюсы:
Минусы:
TTL обновляется при каждом запросе:
Логика:
запрос → проверка → обновление exp → перезапись cookie
Плюсы:
Минусы:
Используются два уровня:
В Iron обычно хранится:
Cookie синхронизируется с refresh механизмом.
После вызова Iron.unseal обязательно выполняется
проверка:
const data = await Iron.unseal(sealed, password, Iron.defaults);
if (data.exp < Date.now()) {
throw new Error('Session expired');
}
Это критический слой безопасности, так как:
Решение:
Результат:
Если серверы распределены:
Решение:
Пользователь логинится
Генерируется токен с exp
Создаётся Iron payload
Устанавливается cookie с maxAge = exp - now
При каждом запросе:
При необходимости:
Когда TTL истекает:
Важно: даже корректно расшифрованные данные не считаются валидными без проверки TTL.
TTL напрямую влияет на:
Короткий TTL:
Длинный TTL:
Баланс определяется типом системы.
Единый конфиг TTL:
const SESSION_TTL = 30 * 60 * 1000;
const session = {
exp: Date.now() + SESSION_TTL
};
const cookie = {
maxAge: SESSION_TTL
};
Iron используется только как транспорт:
При refresh сценарии:
Важно избегать: