Как понимаешь в какой момент нужно обновить токен?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Что такое токен и почему его нужно обновлять?
Токен доступа (access token) — это криптографический ключ, который подтверждает личность пользователя и даёт ему права на выполнение определённых действий. Токены имеют время жизни (TTL — Time To Live), которое может быть от нескольких минут до нескольких часов. После истечения этого времени токен становится невалидным, и пользователь не сможет выполнять защищённые операции.
Обновление токена необходимо, чтобы пользователь оставался авторизованным без необходимости повторного входа. Вместо хранения долгоживущего токена (что снижает безопасность), используется пара: короткоживущий access token и долгоживущий refresh token.
Когда обновлять токен?
Проактивный подход (рекомендуется):
const useAuth = () => {
const refreshInterval = useRef(null);
useEffect(() => {
const expiresIn = getTokenExpiration();
const refreshTime = (expiresIn - 300) * 1000;
refreshInterval.current = setTimeout(() => {
refreshAccessToken();
}, refreshTime);
return () => clearTimeout(refreshInterval.current);
}, []);
};
Реактивный подход (при ошибке):
const api = axios.create({...});
api.interceptors.response.use(
response => response,
async error => {
if (error.response?.status === 401) {
try {
const newToken = await refreshAccessToken();
error.config.headers.Authorization = `Bearer ${newToken}`;
return api(error.config);
} catch (err) {
redirectToLogin();
return Promise.reject(err);
}
}
return Promise.reject(error);
}
);
Практическая реализация в React
export const refreshAccessToken = async () => {
const refreshToken = localStorage.getItem("refresh_token");
if (!refreshToken) {
throw new Error("No refresh token available");
}
const response = await fetch("/api/v1/auth/refresh", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ refresh_token: refreshToken }),
});
if (!response.ok) {
localStorage.removeItem("access_token");
localStorage.removeItem("refresh_token");
window.location.href = "/login";
throw new Error("Failed to refresh token");
}
const { access_token, expires_in } = await response.json();
localStorage.setItem("access_token", access_token);
localStorage.setItem("token_expires_at", Date.now() + expires_in * 1000);
return access_token;
};
export const useAuth = () => {
const [user, setUser] = useState(null);
const refreshTimeoutRef = useRef(null);
const scheduleTokenRefresh = useCallback((expiresIn) => {
const refreshTime = (expiresIn - 60) * 1000;
refreshTimeoutRef.current = setTimeout(async () => {
try {
await refreshAccessToken();
const newExpiresIn = JSON.parse(
atob(localStorage.getItem("access_token").split(".")[1])
).exp - Math.floor(Date.now() / 1000);
scheduleTokenRefresh(newExpiresIn);
} catch (error) {
console.error("Token refresh failed:", error);
setUser(null);
}
}, refreshTime);
}, []);
useEffect(() => {
return () => clearTimeout(refreshTimeoutRef.current);
}, []);
return { user, scheduleTokenRefresh };
};
Хранение токенов: localStorage vs cookies
localStorage: просто, но уязвим для XSS атак. HttpOnly cookies: безопаснее (недоступны JavaScript), защищены от XSS, но требуют дополнительной настройки CSRF. Оптимально: хранить refresh token в HttpOnly cookie, access token в памяти или localStorage.