fix(auth): живая сессия на устройстве — рефреш на холодном старте, grace-окно ротации, без логаута при временных ошибках
- /api/auth/me при 401 делает одну попытку refresh (раньше refresh-retry был
отключён для всех /api/auth/* — холодный старт после 15 мин простоя = логаут)
- ротация: повтор старого refresh-токена в пределах RACE_TOLERANCE_MS (5 мин)
выдаёт новую пару от successor вместо deny; cookie больше не стираются при
stale-токенах (разлогинивались все вкладки устройства); reuse после окна —
revoke family как раньше (тесты обновлены)
- refreshSession различает 401/403/400 (сессия мертва) vs 429/5xx/сеть
(transient — нет logout, отложенный retry)
- единый рефреш: useAuth keep-alive и useOfflineSync переведены на refreshSession;
межвкладочная дедупликация через BroadcastChannel('auth-refresh')
- refreshLimiter: keyGenerator buildRateLimitKey (per-user, не общий IP-бакет офиса)
This commit is contained in:
@@ -270,13 +270,15 @@ export const authLimiter = rateLimit({
|
||||
});
|
||||
|
||||
// Отдельный лимит для обновления токенов — приложение вызывает его автоматически,
|
||||
// поэтому лимит значительно выше чтобы не мешать нормальной работе
|
||||
// поэтому лимит значительно выше чтобы не мешать нормальной работе.
|
||||
// Ключ per-user из JWT (как у apiLimiter): офис за NAT не делит общий бакет.
|
||||
export const refreshLimiter = rateLimit({
|
||||
windowMs: 15 * 60 * 1000,
|
||||
max: 120,
|
||||
message: { error: 'Слишком много запросов обновления токена. Попробуйте позже.' },
|
||||
standardHeaders: true,
|
||||
legacyHeaders: false,
|
||||
keyGenerator: buildRateLimitKey,
|
||||
});
|
||||
|
||||
// Общий API лимит — 1500 запросов за 15 минут
|
||||
|
||||
Reference in New Issue
Block a user