Access-токен жил 60 минут без обновления: фронт не слал response-interceptor на 401, refresh-токен лежал в localStorage неиспользуемым, WebSocket-сокеты (форма, статусы выгрузки) не переподключались после закрытия с auth-кодом, а после редиректа на /login пользователь терял исходную страницу. - tokenRefresh.js: чистые getTokenExp/msUntilRefresh/createSingleFlight (TDD). - auth.js: refreshTokens — обновление токена вне интерсепторов api (без рекурсии), централизованно чистит токены и шлёт auth:expired при неудаче. - client.js: response-interceptor повторяет запрос после обновления токена. - AuthProvider: при старте и по 'auth:expired'/'auth:refreshed' не выкидывает из системы, пока жив refresh; проактивный таймер обновления + visibilitychange. - Routes/LoginPage: PrivateRoute сохраняет исходный location, вход возвращает туда же вместо /tasks; убрана мёртвая ветка loading. - useWebSocket/exports: переподключение после 1008/4401 с одной попыткой refreshTokens() перед тем как сдаться. Issue: #248 (AURORA-1877, эпик AURORA-1876, Критичный приоритет) Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
39 lines
971 B
JavaScript
39 lines
971 B
JavaScript
import { getTokenExp } from './tokenRefresh.js';
|
|
|
|
export const saveAuthTokens = (data) => {
|
|
const { access_token, refresh_token, expires_in } = data;
|
|
|
|
// TODO: раскомментировать, когда поправят expires_in на бэке
|
|
// const expiresAt = Date.now() + expires_in * 1000
|
|
|
|
localStorage.setItem('access_token', access_token);
|
|
localStorage.setItem('refresh_token', refresh_token);
|
|
// localStorage.setItem('expires_at', expiresAt.toString())
|
|
};
|
|
|
|
export const getAuthToken = () => {
|
|
const access_token = localStorage.getItem('access_token');
|
|
|
|
return access_token;
|
|
};
|
|
|
|
export const isTokenExpired = () => {
|
|
const token = getAuthToken();
|
|
if (!token) {
|
|
return true;
|
|
}
|
|
|
|
const exp = getTokenExp(token);
|
|
if (exp === null) {
|
|
return true;
|
|
}
|
|
|
|
const now = Math.floor(Date.now() / 1000);
|
|
return exp < now;
|
|
};
|
|
|
|
export const clearAuthTokens = () => {
|
|
localStorage.removeItem('access_token');
|
|
localStorage.removeItem('refresh_token');
|
|
};
|