При работе с защищёнными API на базе Node.js и механизмов шифрования
вроде @hapi/iron ключевым элементом становится корректная
передача токена между клиентом и сервером. Наиболее распространённый
способ — использование HTTP-заголовка Authorization,
который позволяет унифицировать обработку аутентификационных данных на
уровне протокола.
Заголовок Authorization представляет собой строку,
содержащую схему аутентификации и сам токен:
Authorization: <схема> <значение_токена>
На практике чаще всего используется схема Bearer:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6...
В случае применения @hapi/iron токен обычно представляет
собой «запечатанный» (sealed) объект, содержащий полезную нагрузку, срок
действия и дополнительные параметры безопасности.
Библиотека @hapi/iron позволяет упаковывать данные в
криптографически защищённую строку:
import Iron from '@hapi/iron';
const password = 'super-secure-password';
const payload = {
userId: 42,
role: 'admin',
exp: Date.now() + 1000 * 60 * 15
};
const sealed = await Iron.seal(payload, password, Iron.defaults);
Полученная строка sealed и является токеном, который
передаётся клиенту.
После получения токена клиент сохраняет его (например, в памяти приложения или безопасном хранилище) и добавляет в каждый запрос к защищённым ресурсам:
fetch('/api/profile', {
method: 'GET',
headers: {
Authorization: `Bearer ${token}`
}
});
Использование префикса Bearer важно для унификации
обработки на серверной стороне, даже если сам токен не является JWT.
На сервере первым шагом является парсинг заголовка
Authorization. Обычно он извлекается из объекта
запроса:
const authHeader = request.headers.authorization;
if (!authHeader) {
throw new Error('Отсутствует заголовок Authorization');
}
const [scheme, token] = authHeader.split(' ');
if (scheme !== 'Bearer') {
throw new Error('Неверная схема авторизации');
}
После извлечения токена можно переходить к его расшифровке через
Iron.unseal.
Основная операция — восстановление исходного объекта:
import Iron from '@hapi/iron';
const password = 'super-secure-password';
const unsealed = await Iron.unseal(token, password, Iron.defaults);
Если токен был изменён или повреждён, операция завершится ошибкой, что автоматически защищает систему от подделки данных.
После расшифровки важно проверить срок действия:
if (unsealed.exp < Date.now()) {
throw new Error('Токен истёк');
}
Также на этом этапе могут проверяться роли пользователя, разрешения и дополнительные ограничения доступа.
В архитектуре серверного приложения логично вынести обработку заголовка в middleware:
async function authMiddleware(request, h) {
const header = request.headers.authorization;
if (!header) {
throw new Error('Unauthorized');
}
const [, token] = header.split(' ');
const credentials = await Iron.unseal(token, password, Iron.defaults);
if (credentials.exp < Date.now()) {
throw new Error('Token expired');
}
request.auth = credentials;
return h.continue;
}
Такой подход обеспечивает единообразную проверку авторизации для всех маршрутов.
Схема Bearer не накладывает ограничений на формат
токена, что делает её универсальной для различных механизмов:
Главное требование — единый способ передачи через HTTP-заголовок.
При использовании Authorization важно учитывать
несколько аспектов:
localStorage при чувствительных данных)@hapi/iron дополнительно обеспечивает криптографическую
целостность, что исключает возможность незаметной модификации данных
внутри токена.
На практике часто встречаются типовые проблемы:
authentication
вместо Authorization)seal и
unsealКорректная обработка этих ситуаций должна быть предусмотрена на уровне middleware, чтобы исключить утечки логики в бизнес-код.