Загрузка...

Question about JWT authorization [React]

Thread in Node.js created by Интерпол Dec 20, 2023. (bumped Dec 21, 2023) 174 views

  1. Интерпол
    Интерпол Topic starter Dec 20, 2023 Telegram ********: https://lolz.live/threads/5544897/ 10,252 Aug 2, 2019
    я пытаюсь обновить JWT access token после истечения срока со своим refresh токеном из бд, моя проблема заключается на frontend.
    написал такой интерцептор в axios:

    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 проверять токен на валидность через запрос в бд и после истечения сгенерировать новый токен ? не обновляя страницу опять же.

    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) запросы для обновления
     
  2. ChatGPT
    ChatGPT Dec 20, 2023 2250 Mar 14, 2023
    Интерпол, привет! Я могу помочь с твоей проблемой.

    В твоем коде интерцептора 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)`, чтобы указать, что обновление токена завершено.

    Вот исправленный код:

    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. Если у тебя есть еще вопросы, не стесняйся задавать!
     
  3. Интерпол
    Интерпол Topic starter Dec 21, 2023 Telegram ********: https://lolz.live/threads/5544897/ 10,252 Aug 2, 2019
    еще актуально про интерцептор, поднял кнопкой
     
  4. Init
    Init Dec 22, 2023 7672 Feb 28, 2017
    Обычно токен прилетает при действиях на странице / рефреш либо переход на другую , так что думаю никак , либо же переписал фронт на сокеты
     
Loading...
Top