Дата: 2026-06-11 Статус: Accepted (требует реализации)
Текущая реализация в backend/internal/services/auth.go валидирует refresh токены только по подписи JWT, не сохраняя их в БД. Таблица refresh_tokens создана в миграции 000002_create_users.up.sql но не используется.
| Риск | Последствие |
|---|---|
| Утечка refresh токена | Полный доступ к аккаунту на 30 дней |
| Нет logout / revoke | Пользователь не может завершить сессию на других устройствах |
| Нет ротации | Replay атаки, кража токена не обнаруживается |
| Смена пароля не инвалидирует сессии | Скомпрометированный аккаунт остаётся доступным |
Хранить хеш refresh токена в таблице refresh_tokens с ротацией при каждом использовании.
CREATE TABLE refresh_tokens (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
token_hash VARCHAR(255) NOT NULL, -- SHA-256(token)
expires_at TIMESTAMPTZ NOT NULL, -- now() + 30 days
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
revoked_at TIMESTAMPTZ -- для явного отзыва
);
CREATE UNIQUE INDEX idx_refresh_tokens_token_hash ON refresh_tokens(token_hash);
CREATE INDEX idx_refresh_tokens_user_id ON refresh_tokens(user_id);
Login / Register:
INSERT INTO refresh_tokens (user_id, token_hash, expires_at) VALUES ($1, SHA256($2), $3)access_token (JWT, 15min) + refresh_token (plain, в HttpOnly cookie)Refresh:
SELECT * FROM refresh_tokens WHERE token_hash = SHA256($1) AND expires_at > now() AND revoked_at IS NULLLogout / Password Change / Ban:
UPDATE refresh_tokens SET revoked_at = now() WHERE user_id = $1 AND revoked_at IS NULLCleanup (cron job):
DELETE FROM refresh_tokens WHERE expires_at < now() - interval '1 day'| Вариант | Почему отклонен |
|---|---|
| JWT Blacklist в Redis | Нужно хранить до истечения (30 дней), нет ротации, сложнее очистка |
| Короткий refresh (1 день) без БД | Плохой UX — частый релогин, не решает проблему утечки |
| Access token в куке, refresh в localStorage | localStorage уязвим к XSS, HttpOnly cookie безопаснее |
Положительные:
Отрицательные:
#decision-record #security #jwt #auth #architecture