я пытаюсь обновить JWT access token после истечения срока со своим refresh токеном из бд, моя проблема заключается на frontend. написал такой интерцептор в axios: api.interceptors.response.use( async (response) => { return response }, async (error) => { const originalRequest = error.config if (error.response.status === 401 && !originalRequest._isRetry) { originalRequest._isRetry = true try { const response = await api.get("/account/refresh", { withCredentials: true, }) const newAccessToken = response.data localStorage.setItem("token", newAccessToken) originalRequest.headers["Authorization"] = `Bearer ${newAccessToken}` return api(originalRequest) } catch (e) { console.log("Need to login") } } return Promise.reject(error) } ) JS api.interceptors.response.use( async (response) => { return response }, async (error) => { const originalRequest = error.config if (error.response.status === 401 && !originalRequest._isRetry) { originalRequest._isRetry = true try { const response = await api.get("/account/refresh", { withCredentials: true, }) const newAccessToken = response.data localStorage.setItem("token", newAccessToken) originalRequest.headers["Authorization"] = `Bearer ${newAccessToken}` return api(originalRequest) } catch (e) { console.log("Need to login") } } return Promise.reject(error) } ) но он не работает так как я ожидаю, как мне с использованием useEffects проверять токен на валидность через запрос в бд и после истечения сгенерировать новый токен ? не обновляя страницу опять же. const checkSession = async () => { if (token) { try { const verifiedToken = await validateToken() console.log(verifiedToken) if (verifiedToken) { setConnected(true) setRole(verifiedToken.userData) } else { setConnected(false) setRole(null) } const now = new Date().getTime() const expToken = verifiedToken.exp * 1000 if (now > expToken) { localStorage.removeItem("token") setConnected(false) } if (token && !connected) { console.log("Token refreshed") refreshToken() } } catch (error) { console.error("Error while validating token:", error) } } } useEffect(() => { checkSession() }, [token]) const refreshToken = async () => { try { const response = await get("/refresh") const newToken = response.data console.log(newToken) localStorage.setItem("token", newToken) setToken(newToken) setConnected(true) } catch (error) { console.error("Error in refreshing token:", error) } } JS const checkSession = async () => { if (token) { try { const verifiedToken = await validateToken() console.log(verifiedToken) if (verifiedToken) { setConnected(true) setRole(verifiedToken.userData) } else { setConnected(false) setRole(null) } const now = new Date().getTime() const expToken = verifiedToken.exp * 1000 if (now > expToken) { localStorage.removeItem("token") setConnected(false) } if (token && !connected) { console.log("Token refreshed") refreshToken() } } catch (error) { console.error("Error while validating token:", error) } } } useEffect(() => { checkSession() }, [token]) const refreshToken = async () => { try { const response = await get("/refresh") const newToken = response.data console.log(newToken) localStorage.setItem("token", newToken) setToken(newToken) setConnected(true) } catch (error) { console.error("Error in refreshing token:", error) } } каков правильный подход? мне нужно генерить новые токен по истечению старой не отправляй каждый раз при обновлении (useEffect) запросы для обновления
Интерпол, привет! Я могу помочь с твоей проблемой. В твоем коде интерцептора axios, ты пытаешься обновить access token после истечения срока действия refresh token. Однако, у тебя есть несколько проблем в коде. 1. Вместо `api.get("/account/refresh")`, ты должен использовать `api.post("/account/refresh")`, так как обычно обновление токена выполняется с помощью HTTP метода POST. 2. Вместо `response.data`, ты должен использовать `response.data.accessToken`, чтобы получить новый access token из ответа сервера. 3. Вместо `localStorage.setItem("token", newAccessToken)`, ты должен использовать `localStorage.setItem("accessToken", newAccessToken)`, чтобы сохранить новый access token в localStorage. 4. Вместо `originalRequest.headers["Authorization"] = `Bearer ${newAccessToken}``, ты должен использовать `originalRequest.headers.Authorization = `Bearer ${newAccessToken}``, чтобы обновить заголовок Authorization с новым access token. Теперь касательно использования useEffect для проверки валидности токена и обновления его при истечении срока действия. Твой подход в целом верный, но есть несколько замечаний. 1. Вместо `if (token && !connected)`, ты должен использовать `if (token && !connected && !refreshingToken)`, чтобы избежать повторных запросов на обновление токена, когда уже выполняется запрос на обновление. 2. Вместо `localStorage.removeItem("token")`, ты должен использовать `localStorage.removeItem("accessToken")`, чтобы удалить старый access token из localStorage. 3. Вместо `setToken(newToken)`, ты должен использовать `localStorage.setItem("accessToken", newToken)`, чтобы сохранить новый access token в localStorage. 4. Вместо `setConnected(true)`, ты должен использовать `setConnected(true)` и `setRefreshingToken(false)`, чтобы указать, что обновление токена завершено. Вот исправленный код: const checkSession = async () => { if (token) { try { const verifiedToken = await validateToken() console.log(verifiedToken) if (verifiedToken) { setConnected(true) setRole(verifiedToken.userData) } else { setConnected(false) setRole(null) } const now = new Date().getTime() const expToken = verifiedToken.exp * 1000 if (now > expToken) { localStorage.removeItem("accessToken") setConnected(false) } if (token && !connected && !refreshingToken) { console.log("Token refreshed") refreshToken() } } catch (error) { console.error("Error while validating token:", error) } } } useEffect(() => { checkSession() }, [token]) const refreshToken = async () => { try { setRefreshingToken(true) const response = await post("/refresh") const newToken = response.data.accessToken console.log(newToken) localStorage.setItem("accessToken", newToken) setConnected(true) setRefreshingToken(false) } catch (error) { console.error("Error in refreshing token:", error) setRefreshingToken(false) } } JavaScript const checkSession = async () => { if (token) { try { const verifiedToken = await validateToken() console.log(verifiedToken) if (verifiedToken) { setConnected(true) setRole(verifiedToken.userData) } else { setConnected(false) setRole(null) } const now = new Date().getTime() const expToken = verifiedToken.exp * 1000 if (now > expToken) { localStorage.removeItem("accessToken") setConnected(false) } if (token && !connected && !refreshingToken) { console.log("Token refreshed") refreshToken() } } catch (error) { console.error("Error while validating token:", error) } } } useEffect(() => { checkSession() }, [token]) const refreshToken = async () => { try { setRefreshingToken(true) const response = await post("/refresh") const newToken = response.data.accessToken console.log(newToken) localStorage.setItem("accessToken", newToken) setConnected(true) setRefreshingToken(false) } catch (error) { console.error("Error in refreshing token:", error) setRefreshingToken(false) } } Теперь твой код должен правильно обновлять access token при истечении срока действия refresh token. Если у тебя есть еще вопросы, не стесняйся задавать!
Обычно токен прилетает при действиях на странице / рефреш либо переход на другую , так что думаю никак , либо же переписал фронт на сокеты