What is the best method for ensuring a user remains logged in even after their access token expires, requiring them to log in again to resume their normal

Currently utilizing the Nuxt-axios module alongside a proxy.

Implemented common error handling code in

Plugins/axios.js

export default function({ $axios, __isRetryRequest, store, app, redirect , payload , next}) {
  $axios.onRequest(config => {
    if (app.$cookies.get('at') && app.$cookies.get('rt') && config.url != '/post_login/') {
      config.headers.common['Authorization'] = `Bearer ${app.$cookies.get('at')}`;
    }
  });

  $axios.onResponseError(err => {
    const code = parseInt(err.response && err.response.status)

    let originalRequest = err.config;

    if (code === 401) {
      originalRequest.__isRetryRequest = true;

      store
        .dispatch('LOGIN', { grant_type: 'refresh_token', refresh_token: app.$cookies.get('rt')})
        .then(res => {
          originalRequest.headers['Authorization'] = 'Bearer ' + app.$cookies.get('at');
          return app.$axios(originalRequest);
        })
        .catch(error => {
          console.log(error);
        });
    }

    // Error handling for status code 422
    if (code == 422) {
      throw err.response;
    }

  });
}

In the index file within the pages folder

Pages/index.vue

<template>
  <section>Component data</section>
</template>

<script type="text/javascript">
export default {
  async asyncData({ route, store }) {
    await store.dispatch('GET_BANNERS');
  }
}
</script>

All API calls are handled in a stores/actions.js file.

When refreshing the page, the first API request from 'asyncData' will be made. If this initial request ('GET_BANNERS') encounters a 401 unauthorized error, the following error is displayed:

Error: Request failed with status code 401

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

To address this issue, there are additional questions:

Additional Queries:

1) When defining common error handling code in axios, how can I update store data again after receiving a 401 response on the original request?

2) Can someone provide guidance on best practices for setting authorization headers and handling errors like 400, 401, and 422?

Answer №1

$axios.onResponseError(error => {
  const errorCode = parseInt(error.response && error.response.status);

  let originalReq = error.config;
  if (errorCode == 401) {
    originalReq.__isRetryReq = true;

    let authToken = app.$cookies.get('rt');

    return new Promise((resolve, reject) => {
      let req = $axios
        .post(`/login`, { grant_type: 'refresh_token', refresh_token: authToken })
        .then(res => {

          if (res.status == 200) {

              app.$cookies.set('access', res.data.access_token);
              app.$cookies.set('refresh', res.data.refresh_token);
              originalReq.headers['Authorization'] = `Bearer ${res.data.access_token}`;
          }
          resolve(res);
        }).catch(err => {
          reject("error message");
        })

      })
      .then(result => {
        return $axios(originalReq);
      }).catch(err => {
        app.router.push('/login');
      });
  }
});

@canet-robern hope this resolves your issue!!

Answer №2

The occurrence of ERR_HTTP_HEADERS_SENT indicates a flaw in the server-side code, resulting in the error being triggered before the HTTP headers are processed.

To effectively manage and retry Axios requests following 4xx errors, refer to the implementation below:

Vue.prototype.$axios = axios.create(
  {
    headers:
      {
        'Content-Type': 'application/json',
      },
    baseURL: process.env.API_URL
  }
);

Vue.prototype.$axios.interceptors.request.use(
  config =>
  {
    events.$emit('show_spin');
    let token = getTokenID();
    if(token && token.length) config.headers['Authorization'] = token;
    return config;
  },
  error =>
  {
    events.$emit('hide_spin');
    if (error.status === 401) VueRouter.push('/login');
    else throw error;
  }
);
Vue.prototype.$axios.interceptors.response.use(
  response =>
  {
    events.$emit('hide_spin');
    return response;
  },
  error =>
  {
    events.$emit('hide_spin');
    return new Promise(function(resolve,reject)
    {
      if (error.config && error.response && error.response.status === 401 && !error.config.__isRetry)
      {
        myVue.refreshToken(function()
        {
          error.config.__isRetry = true;
          error.config.headers['Authorization'] = getTokenID();
          myVue.$axios(error.config).then(resolve,reject);
        },function(flag) // true = invalid session, false = something else
        {
          if(process.env.NODE_ENV === 'development') console.log('Could not refresh token');
          if(getUserID()) myVue.showFailed('Could not refresh the Authorization Token');
          reject(flag);
        });
      }
      else throw error;
    });
  }
); 

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

React UseEffect - Triggering only when data has been updated

In my current situation, I am facing a dilemma with the useEffect hook. I need it to not run on the initial render, but only when specific data is rendered, such as home.matchsPlayed and home.winHome. This is what my code looks like: useEffect(() => ...

Conditions for JQuery Ajax handlingIs there anything specific you would

I am looking to implement a try-catch scenario in Laravel where, if successful, a certain message will appear and if it fails, a different message will be displayed. However, when executed successfully, it seems to display the second message instead. $.a ...

Please click the provided link to display the data in the div. Unfortunately, the link disappearance feature is currently not

What I'm Looking For I want the data to be displayed when a user clicks on a link. The link should disappear after it's clicked. Code Attempt <a href="javascript:void(0);" class="viewdetail more" style="color:#8989D3!important;">vi ...

Preventing jQuery from removing child elements while inserting data through ajax

When I try to insert data into an HTML structure using the code below, only one of the elements displays at a time. It seems like when I use Ajax to insert data, the child elements are being removed. How can I prevent this without having to change the stru ...

Is it possible to rearrange the node_modules directory?

Within the node_modules directory, there exists a large and extensive collection of modules. These modules are often duplicated in various sub-folders throughout the directory, with some containing identical versions while others differ by minor versions. ...

Working with React and MongoDB: Loading multiple arrays of object states depending on conditions

Hello everyone! This is my first time reaching out for help here, so please bear with me if I miss any key details. I'm currently facing an issue while trying to load three different object arrays based on the boolean values 'started' and &a ...

Identifying periods of inactivity using an embedded iframe

I have developed a website that showcases a three.js model within an iframe. My goal is to redirect users back to the homepage (index.html) after they have been inactive for a specified amount of time. While I have managed to achieve this using JavaScript, ...

How to simulate keyboard events when a dropdown list is opened in an Angular application

Requirement- A situation arises where upon opening the dropdown menu, pressing the delete key on the keyboard should reset the index to -1. Steps to reproduce the issue: 1. Click on the dropdown and select an option from the menu. 2. Click on the dropdow ...

What is the functionality behind a free hosting website?

Is anyone familiar with websites like Hostinghood, where users can create a subdomain and upload HTML, CSS, etc.? I'm curious about how they operate and how I can create a similar site. This is my first question here, so please respond instead of disl ...

Swiper: What methods can be used to classify the nature of an event?

Currently, I am utilizing Swiper for React in my project. I find myself in need of implementing a different effect when the user swipes versus using buttons to switch between active slides. Upon examining the swipe object for pertinent details regarding ...

ReactJS: streamlining collection method calls using re-base helper functions

I have been struggling to find a way to integrate ReactJS with firebase. Fortunately, I came across the amazing re-base repository which perfectly fits my needs. fb-config.js var Rebase = require('re-base'); var base = Rebase.createClass({ ...

Is there a way to directly access the React component that was clicked?

I'm looking to dynamically change the class of a component when clicked. By using state to create a new component with properties such as name and done (initiated as false), which are then added to the todos array, I want to find out how to identify t ...

What are some secure methods for integrating iframes into an Angular 7 project?

Is there a secure method to set the URL for an iframe without bypassing security measures like using this.domsanitizer.bypassSecurityTrustResourceUrl(url)? While this approach may be flagged as a high vulnerability by tools such as Veracode, is there a w ...

Ways to verify user authentication for navigating Vue routes

Working on a Single Page Application with Vue front-end, Express, and Parse (parse-platform) for back-end. After authenticating the user, I store their info in a session variable req.session.user = result; before sending it back to the client using res.sta ...

Altering the way in which URL parameters are attached to links depending on the destination

Our company utilizes Unbounce to create PPC landing pages on a subdomain, which then direct users back to our main website. We have implemented code that appends the AdWords gclid variable to outgoing links: $(document).ready(function() {var params = win ...

Learn the process of incorporating a plugin into a React JS project

As a ReactJs beginner, I am encountering an issue while trying to import a new plugin in my react app. I am currently working on React without using node or npm as shown below. <!-- some HTML --> <script src="https://unpkg.com/babel-standalone@6 ...

What is the best way to implement an 'onKeyPress' event listener for a <canvas> element in a React application?

I've been working with React for a while now and I understand how its event system functions. However, I've run into an issue where the onKeyPress event doesn't seem to be triggering on a <canvas> element. Surprisingly, it's not w ...

Changing the appearance of a website by switching CSS stylesheets according to the size of the browser

Trying to build two versions of my website: one for mobile devices or small browsing windows, and another for large browser windows. Looking to link HTML to different style sheets based on browser size. Current attempt in code only addresses total screen ...

Remove all spaces from input fields in angular Typescript, excluding the enter key

I've encountered an issue where the code below removes all spaces, but it's also removing the enter key. Is there a way to remove only spaces and not affect the enter key? static stripDoubleSpaces(str: string): string { if (!!str) { ...

Using JQuery to switch classes and activate events

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <body> <span class="fake_h">Too</span> </body> <script> $('.fake_h').click(function() { $(this).addClass( ...