Обновление токена после успешной проверки

Библиотека @hapi/iron реализует механизм криптографической упаковки данных (sealing) и их последующего восстановления (unsealing). В отличие от классических JWT, где данные остаются читаемыми, Iron формирует полностью зашифрованную строку, содержащую полезную нагрузку и метаданные проверки целостности.

Процесс состоит из двух базовых операций:

  • seal — преобразование объекта в защищённую строку
  • unseal — восстановление исходного объекта при наличии корректного пароля

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


Проверка токена перед обновлением

Перед обновлением токена выполняется его полная проверка через unseal. На этом этапе происходит:

  • дешифровка строки
  • проверка HMAC-подписи
  • проверка срока действия (ttl)
  • валидация структуры данных

Только после успешного завершения этих шагов токен считается валидным и допускается к обновлению.

import Iron from '@hapi/iron';

const password = 'strong-encryption-password';

const unsealed = await Iron.unseal(
  sealedToken,
  password,
  Iron.defaults
);

// если выполнение дошло сюда — токен валиден

Причины обновления токена после успешной проверки

Обновление токена после успешной валидации используется не как обязательный шаг, а как механизм повышения безопасности и управления сессией. Основные сценарии:

  • продление срока жизни активной сессии
  • ротация ключей шифрования
  • обновление пользовательских прав (roles/permissions)
  • защита от повторного использования устаревших токенов
  • реализация sliding session (скользящего времени жизни)

В отличие от статических токенов, динамическое обновление позволяет уменьшить окно атаки при компрометации.


Ротация токена как часть процесса проверки

После успешного 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 extension)

Одним из ключевых сценариев является продление времени жизни токена при активности пользователя. После успешной проверки пересчитывается 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-значения оно заменяет старый токен в канале передачи данных:

  • HTTP cookie
  • Authorization header
  • session storage (в случае API gateway)

Пример обновления cookie:

const newToken = await Iron.seal(data, password, Iron.defaults);

response.setHeader('Se t-Cookie', `session=${newToken}; HttpOnly; Secure; Path=/`);

Таким образом, клиент автоматически начинает использовать обновлённую версию без дополнительной логики.


Sliding session: непрерывное продление активности

Механизм обновления после проверки часто используется для реализации sliding session. Логика заключается в том, что каждый валидный запрос продлевает срок жизни токена.

Алгоритм:

  1. Токен проверяется через unseal
  2. При успешной проверке создаётся новый токен
  3. Новый токен отправляется клиенту
  4. Старый токен становится устаревшим после следующего запроса

Это позволяет поддерживать активную сессию только при фактическом использовании системы.


Контроль повторного использования токенов

Обновление токена после проверки также снижает риск 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;
}

Безопасная стратегия обновления токена

На практике обновление токена после успешной проверки строится вокруг нескольких принципов:

  • обновление только после полной валидации
  • использование актуального ключа шифрования
  • ограничение TTL для предотвращения долгоживущих токенов
  • обязательная замена старого значения новым
  • минимизация неизменяемых данных внутри токена

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