Coder Social home page Coder Social logo

Comments (10)

revmischa avatar revmischa commented on May 21, 2024

Like a callback? Not really but feel free to send a PR!

from axios-jwt.

florianmartens avatar florianmartens commented on May 21, 2024

That was a fast response :-D Thanks!

I just saw that it's probably easiest to just add a catch statement to the requestRefetch function and do a force logout from there.

from axios-jwt.

mvanroon avatar mvanroon commented on May 21, 2024

@florianmartens additionally you could set up your backend so that it also refreshes and returns refresh tokens every time you refresh your access token. This way a user is logged in for as long as they use your (web) app every now and then (depending on your refresh token expiration)

#16

from axios-jwt.

Maidomax avatar Maidomax commented on May 21, 2024

@mvanroon It still leaves a problem that the refresh token will expire at some point in the future, and the call to the backend will throw an exception that will not be handled by the catch() method.

from axios-jwt.

mvanroon avatar mvanroon commented on May 21, 2024

@mvanroon It still leaves a problem that the refresh token will expire at some point in the future, and the call to the backend will throw an exception that will not be handled by the catch() method.

That’s a good thing right? It will cause the axios call to throw an error which you can catch. If the status code is 401 you navigate the user to the login page

from axios-jwt.

Maidomax avatar Maidomax commented on May 21, 2024

@mvanroon I get an error in the console even though I chained a catch() to the call. I'm assuming that's because the interceptor uses a different axios client instance to refresh the tokens. Maybe I'm missing something...

from axios-jwt.

Maidomax avatar Maidomax commented on May 21, 2024

When I create my refresh function llike this:

const requestRefresh = (refresh_token) => {
    return axios.post(`${appConfig.base_url}/api/v1/auth/refresh_token`, { refresh_token })
        .then(response => {
            return {
                accessToken: response.data.access_token,
                refreshToken: response.data.refresh_token
            };
        }).catch (e => Promise.reject(e));
};

Then it sort of works, but the catch() method on my api call does not receieve a status code of 401. It receives an exception that looks like:

Error: Unable to refresh access token for request due to token refresh error: Got 401 on token refresh; clearing both auth tokens
    authTokenInterceptor authTokenInterceptor.ts:209
    step axios-jwt.js:2449
    verb axios-jwt.js:2396
    rejected axios-jwt.js:2374
    promise callback*step axios-jwt.js:2380
    __awaiter axios-jwt.js:2382
    __awaiter axios-jwt.js:2364
    authTokenInterceptor authTokenInterceptor.ts:182

I would expect to get an authorization error and redirect the user to the login page. Is there a way to return the refresh token endpoint's response from the interceptor, and handle it as if I don't have a token in the client. I am unauthorized, it should be handled in the same manner.

from axios-jwt.

mvanroon avatar mvanroon commented on May 21, 2024

Thanks for the detailed response. I suppose we should re-throw the exception received from the refresh call and alter the message (prefixing it with ‘Unable to refresh token:’) instead of throwing an entirely new exception. This should be the general idea imo:

async submitForm(values) {
  try {
    await axiosInstance.post(‘/authorized-endpoint’, values)
  } catch (error) {
    if (error.response.status === 401) {
      navigate(‘/login’)
    } else {
      // handle other exceptions
    }
  }
}

An alternative would be to allow one to specify a callback that would be called (onRefreshError) when refreshing fails.

applyAuthTokenInterceptor(axiosInstance, {
  requestRefresh,
  onRefreshError: (error) => {
      navigate(‘/login’)
    }
  }
})

Or both :-)

from axios-jwt.

Maidomax avatar Maidomax commented on May 21, 2024

@mvanroon The problem is that the exception thrown when I try to fetch something from the api does not have error.response.status === 401 because the exception is thrown from the interceptor, without returning the error response from the token refresh endpoint. That sort of makes sense since that endpoint is not the endpoint I'm sending a request to.

The alternative solution would probably work, but I find it sort of icky to inject my router into my rest api client initialization, and not informing the caller of what happened to the request.

For now, I handle all the other statuses first, and than in the end, I just assume that the error was an authorization error.

            this.getData()
                .then((m) => console.log(m))
                .catch((e) => {
                    if (e.response.status === 404) {
                        alert("Resource not found");
                    } else if (e.response.status === 403) {
                        alert("You are not allowed to do that");
                    } else {
                        // Here I just assume that the user is not logged in
                        this.$router.push({
                            name: "login",
                            query: {
                                redirect: this.$route.fullPath,
                            },
                        });
                    }
                });

Also icky, but the least icky option, I think. I with I could just get an exception with the 401 response.

from axios-jwt.

momocode-de avatar momocode-de commented on May 21, 2024

I am dealing with the same problem right now. This is what my requestRefresh function looked like at first:

async requestRefresh(refresh) {
  // Notice that this is the global axios instance!
  const response = await axios.post('/api/token/refresh', { refresh_token: refresh });
  return response.data.token;
};

The problem was that when the backend returned a 401 because the refresh token expired, the following exception came up and my application didn't load properly:

Uncaught (in promise) Error: Unable to refresh access token for request due to token refresh error: Got 401 on token refresh; clearing both auth tokens
    at authTokenInterceptor.js:247:1
    at step (authTokenInterceptor.js:33:1)
    at Object.throw (authTokenInterceptor.js:14:46)
    at rejected (authTokenInterceptor.js:6:42)

Now I have changed my code to this:

async requestRefresh(refresh) {
  try {
    // Notice that this is the global axios instance!
    const response = await axios.post('/api/token/refresh', { refresh_token: refresh });
    return response.data.token;
  } catch (error) {
    if (error.response && error.response.status === 401) {
      this.logout();
    }
  }
};

This looks better now. The logic of my "logout" function is executed and my application loads as I expect it to. However, the following exception still appears in the console:

Uncaught (in promise) Error: Unable to refresh access token for request due to token refresh error: Failed to refresh auth token: requestRefresh must either return a string or an object with an accessToken
    at authTokenInterceptor.js:247:1
    at step (authTokenInterceptor.js:33:1)
    at Object.throw (authTokenInterceptor.js:14:46)
    at rejected (authTokenInterceptor.js:6:42)

The exception occurs because I do not make a return in case of an error, since there is nothing I can return. Returning "null" doesn't work either. I think the code could be improved to also accept a "null" and handle it accordingly.

from axios-jwt.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.