Загрузка...

Вопрос по JWT-авторизации [React]

Тема в разделе Node.js создана пользователем Интерпол 20 дек 2023. (поднята 21 дек 2023) 175 просмотров

  1. Интерпол
    Интерпол Автор темы 20 дек 2023 Telegram ********: https://lolz.live/threads/5544897/ 10 253 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 20 дек 2023 2250 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. Интерпол
    Интерпол Автор темы 21 дек 2023 Telegram ********: https://lolz.live/threads/5544897/ 10 253 2 авг 2019
    еще актуально про интерцептор, поднял кнопкой
     
  4. Init
    Init 22 дек 2023 7818 28 фев 2017
    Обычно токен прилетает при действиях на странице / рефреш либо переход на другую , так что думаю никак , либо же переписал фронт на сокеты
     
Загрузка...
Top