Токены с ограниченными правами (scoped tokens) — это механизм контроля доступа, при котором выданный токен содержит не только факт аутентификации, но и строго определённый набор разрешений (scope). В отличие от «полных» токенов, такие токены позволяют выполнять лишь ограничённый набор операций, что существенно снижает риски безопасности.
В библиотеке Iron для JavaScript scoped tokens реализуются через шифрование полезной нагрузки (payload), в которую включаются данные о правах доступа, сроке действия и дополнительных ограничениях.
Использование scoped tokens решает несколько ключевых задач:
Iron не использует JWT в чистом виде, но концептуально структура похожа. Токен представляет собой зашифрованную строку, содержащую:
Пример payload для scoped token:
{
"userId": 123,
"scope": ["read:profile", "edit:settings"],
"expiresAt": 1715000000000
}
Для работы с Iron используется пакет @hapi/iron.
Пример генерации токена:
import Iron from '@hapi/iron';
const password = 'super-secure-password';
const payload = {
userId: 123,
scope: ['read:data'],
expiresAt: Date.now() + 1000 * 60 * 10 // 10 минут
};
const token = await Iron.seal(payload, password, Iron.defaults);
console.log(token);
Ключевые моменты:
seal шифрует данные и возвращает токенconst unsealed = await Iron.unseal(token, password, Iron.defaults);
if (unsealed.expiresAt < Date.now()) {
throw new Error('Token expired');
}
console.log(unsealed.scope);
Важно:
Scoped tokens бесполезны без строгой проверки прав. Обычно реализуется middleware:
function requireScope(requiredScope) {
return (req, res, next) => {
const token = req.headers.authorization;
Iron.unseal(token, password, Iron.defaults)
.then(data => {
if (!data.scope.includes(requiredScope)) {
return res.status(403).send('Forbidden');
}
req.user = data;
next();
})
.catch(() => res.status(401).send('Unauthorized'));
};
}
Применение:
app.get('/profile', requireScope('read:profile'), (req, res) => {
res.send('Profile data');
});
Scopes удобно строить по принципу иерархии:
read:* — доступ ко всем операциям чтенияwrite:* — доступ ко всем операциям записиadmin:* — полный доступПример расширенной проверки:
function hasScope(userScopes, required) {
return userScopes.includes(required) ||
userScopes.includes(required.split(':')[0] + ':*') ||
userScopes.includes('*');
}
Scoped tokens могут содержать дополнительные ограничения:
{
"scope": ["read:file"],
"resourceId": "file_123"
}
Проверка:
if (data.resourceId !== requestedId) {
throw new Error('Access denied');
}
{
"ip": "192.168.1.1"
}
{
"device": "mobile"
}
Scoped tokens часто используются как временные ключи доступа:
Пример:
const payload = {
action: 'upload',
scope: ['upload:file'],
expiresAt: Date.now() + 1000 * 60 // 1 минута
};
Scoped tokens позволяют делегировать права от одного сервиса другому.
Сценарий:
Пример:
const delegatedToken = await Iron.seal({
scope: ['read:public-data'],
issuedBy: 'service-A'
}, password, Iron.defaults);
Iron не хранит токены на сервере, поэтому отзыв реализуется через:
Пример:
{
"userId": 123,
"scope": ["read"],
"version": 2
}
Проверка:
if (data.version !== currentUserTokenVersion) {
throw new Error('Token revoked');
}
Так как payload зашифрован, изменить scope невозможно без знания пароля. Однако важно:
Рекомендуется использовать разные конфигурации:
Пример:
const authPassword = 'auth-secret';
const apiPassword = 'api-secret';
Генерация токена:
const token = await Iron.seal({
fileId: 'file_123',
scope: ['read:file'],
expiresAt: Date.now() + 300000
}, password, Iron.defaults);
Проверка:
const data = await Iron.unseal(token, password, Iron.defaults);
if (!data.scope.includes('read:file')) {
throw new Error('No permission');
}
if (data.fileId !== requestedFileId) {
throw new Error('Wrong file');
}
Наиболее распространённые проблемы:
*)Iron использует криптографические операции:
Это делает токены:
Для оптимизации:
Сложные системы используют:
Пример расширенного payload:
{
"roles": ["editor"],
"permissions": ["edit:article"],
"attributes": {
"department": "media"
}
}
| Характеристика | Iron | JWT |
|---|---|---|
| Шифрование | Да (по умолчанию) | Нет (обычно только подпись) |
| Читаемость | Нет | Да |
| Безопасность payload | Высокая | Средняя |
| Scoped tokens | Реализуются вручную | Через claims |
Scoped tokens в Iron позволяют строить гибкую, безопасную систему авторизации без необходимости хранения сессий на сервере, при этом сохраняя полный контроль над содержимым и логикой проверки токена.