Библиотека @hapi/iron реализует механизм
криптографической упаковки данных (sealing) и их последующего
восстановления (unsealing). В отличие от классических JWT, где данные
остаются читаемыми, Iron формирует полностью зашифрованную строку,
содержащую полезную нагрузку и метаданные проверки целостности.
Процесс состоит из двух базовых операций:
Основная ценность подхода заключается в невозможности модификации данных без знания секретного ключа и в контролируемом сроке жизни токена.
Перед обновлением токена выполняется его полная проверка через
unseal. На этом этапе происходит:
ttl)Только после успешного завершения этих шагов токен считается валидным и допускается к обновлению.
import Iron from '@hapi/iron';
const password = 'strong-encryption-password';
const unsealed = await Iron.unseal(
sealedToken,
password,
Iron.defaults
);
// если выполнение дошло сюда — токен валиден
Обновление токена после успешной валидации используется не как обязательный шаг, а как механизм повышения безопасности и управления сессией. Основные сценарии:
В отличие от статических токенов, динамическое обновление позволяет уменьшить окно атаки при компрометации.
После успешного unseal часто выполняется немедленное
создание нового sealed-значения с обновлёнными параметрами. Такой подход
формирует цепочку доверенных состояний с ограниченным временем
жизни.
import Iron from '@hapi/iron';
const password = 'strong-encryption-password';
async function verifyAndRotate(oldToken) {
const data = await Iron.unseal(oldToken, password, Iron.defaults);
const upd atedData = {
...data,
lastRefresh: Date.now()
};
const newToken = await Iron.seal(
updatedData,
password,
Iron.defaults
);
return newToken;
}
Одним из ключевых сценариев является продление времени жизни токена
при активности пользователя. После успешной проверки пересчитывается
ttl или создаётся новый объект с обновлённым временем
истечения.
const session = await Iron.unseal(token, password, Iron.defaults);
const refreshedSession = {
...session,
exp: Date.now() + 1000 * 60 * 30 // +30 минут
};
const rotatedToken = await Iron.seal(
refreshedSession,
password,
Iron.defaults
);
Такой подход предотвращает неожиданное завершение сессии при активной работе.
В продакшн-системах часто используется несколько паролей одновременно. Iron поддерживает массив ключей, где первый считается активным, а остальные — резервными для расшифровки старых токенов.
Это позволяет выполнять безопасную ротацию:
const passwords = ['new-secret', 'old-secret'];
const unsealed = await Iron.unseal(token, passwords, Iron.defaults);
После успешной проверки токен всегда пересоздаётся с актуальным ключом.
После генерации нового sealed-значения оно заменяет старый токен в канале передачи данных:
Пример обновления cookie:
const newToken = await Iron.seal(data, password, Iron.defaults);
response.setHeader('Se t-Cookie', `session=${newToken}; HttpOnly; Secure; Path=/`);
Таким образом, клиент автоматически начинает использовать обновлённую версию без дополнительной логики.
Механизм обновления после проверки часто используется для реализации sliding session. Логика заключается в том, что каждый валидный запрос продлевает срок жизни токена.
Алгоритм:
unsealЭто позволяет поддерживать активную сессию только при фактическом использовании системы.
Обновление токена после проверки также снижает риск replay-атак. Если злоумышленник получает старую версию токена, она быстро становится недействительной после первого же валидного запроса пользователя.
Дополнительно может использоваться серверное состояние:
jti или аналогичного поляПри работе с обновлением токенов в Iron важно учитывать ряд особенностей:
unseal полностью блокирует обновлениеТипичный сценарий обработки ошибок:
try {
const data = await Iron.unseal(token, password, Iron.defaults);
return await Iron.seal(data, password, Iron.defaults);
} catch (err) {
// токен недействителен — обновление невозможно
return null;
}
На практике обновление токена после успешной проверки строится вокруг нескольких принципов:
Такая модель позволяет сохранять баланс между безопасностью и удобством работы с сессиями, сохраняя контроль над жизненным циклом токенов без усложнения клиентской логики.