feat(auth): шаг 0.6 — TTL access 15 минут + хэширование refresh/reset-токенов в БД
Some checks are pending
Branch Check / Type Check & Build (push) Waiting to run
Some checks are pending
Branch Check / Type Check & Build (push) Waiting to run
- server/utils/jwt.ts: дефолт JWT_ACCESS_EXPIRES 30d → 15m (env сохранено), hashToken() (sha256 hex) - migrations/0082_token_hashes.sql: *_hash колонки в user_sessions/users, DELETE FROM user_sessions (глобальный разлогин), legacy plain-колонки сохранены, но не пишутся - storage: lookup/отзыв сессий и reset-токенов по хэшу; markSessionReplaced по id сессии - auth.service: ротация в rotateFamilySession(), grace-period ротирует активную сессию вместо возврата plain-токена - auth.core.routes: forgot/reset-password пишут/ищут sha256-хэш, plain только в письме - tests/token-security.test.ts: 12 тестов (выпуск по хэшу, ротация, reuse detection, grace, reset) - .env.example, swagger, IMPLEMENTATION_LOG.md обновлены Проверки: npm run check чисто, vitest 118/118, lint 0 errors, build собирается
This commit is contained in:
28
migrations/0082_token_hashes.sql
Normal file
28
migrations/0082_token_hashes.sql
Normal file
@@ -0,0 +1,28 @@
|
||||
-- Шаг 0.6 (production-готовность): хэширование refresh/reset-токенов в БД.
|
||||
-- Plain-токены больше не хранятся: в БД пишется только sha256-хэш (hex, 64 символа).
|
||||
-- Refresh-сессии живут в user_sessions, reset-токены — в users (отдельных таблиц нет).
|
||||
--
|
||||
-- ВАЖНО: миграция инвалидирует ВСЕ существующие сессии и reset-ссылки
|
||||
-- (глобальный разлогин). Legacy-колонки с plain-токенами НЕ удаляются
|
||||
-- (отложено на отдельную миграцию), но больше не пишутся.
|
||||
|
||||
ALTER TABLE user_sessions ADD COLUMN IF NOT EXISTS refresh_token_hash VARCHAR(64);
|
||||
ALTER TABLE user_sessions ADD COLUMN IF NOT EXISTS parent_refresh_token_hash VARCHAR(64);
|
||||
ALTER TABLE user_sessions ADD COLUMN IF NOT EXISTS replaced_by_token_hash VARCHAR(64);
|
||||
ALTER TABLE users ADD COLUMN IF NOT EXISTS reset_password_token_hash VARCHAR(64);
|
||||
|
||||
-- Глобальный разлогин: старые строки содержат plain-токены и без хэша бесполезны.
|
||||
DELETE FROM user_sessions;
|
||||
UPDATE users SET reset_password_token = NULL, reset_password_expires = NULL
|
||||
WHERE reset_password_token IS NOT NULL;
|
||||
|
||||
-- refresh_token больше не пишется — снимаем NOT NULL (саму колонку оставляем).
|
||||
ALTER TABLE user_sessions ALTER COLUMN refresh_token DROP NOT NULL;
|
||||
ALTER TABLE user_sessions ALTER COLUMN refresh_token_hash SET NOT NULL;
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS user_sessions_refresh_token_hash_key
|
||||
ON user_sessions (refresh_token_hash);
|
||||
CREATE INDEX IF NOT EXISTS user_sessions_parent_refresh_token_hash_idx
|
||||
ON user_sessions (parent_refresh_token_hash);
|
||||
CREATE INDEX IF NOT EXISTS users_reset_password_token_hash_idx
|
||||
ON users (reset_password_token_hash);
|
||||
Reference in New Issue
Block a user