Blog
Refresh Token using Axios Interceptors

Refresh Token using Axios Interceptors

Understand what Interceptors are and what a Refresh Token is.

17 de junho de 2021

This is a republication of the blog post by Vinnicius Gomes – Senior Frontend Engineer at Zappts.

Refresh token diagram

Axios is an HTTP client that works both in the browser and in Node.Js. The library is basically an API that knows how to interact with both XMLHttpRequest and Node’s HTTP interface. This means that the same code used to make Ajax requests in the browser also works on the server side.

Let’s talk about Interceptors

Interceptors are, as the name suggests, interceptors. In Axios we can use them to execute some function before the Request and/or Response is initiated.

Here’s an example:

// Adding a Request interceptor
axios.interceptors.request.use(function (config) {
   // Do something before the request is sent
   return config;
 }, function (error) {
   // Do something with request error
   return Promise.reject(error);
 });
// Adding a Response interceptor
axios.interceptors.response.use(function (response) {
   // Any status code that falls within 2xx causes this function to trigger
   // Do something with response data
   return response;
 }, function (error) {
   // Any status codes that falls outside 2xx causes this function to trigger
   // Do something with response error
   return Promise.reject(error);
 });

You can find this example in the Axios documentation.

Now that you know what an interceptor is, let’s get to what matters!

If you don’t know what a Refresh Token is, take a read here.

So let’s start our Refresh Token, let’s create a file called api.js:

import axios from "axios";

const api = axios.create({
 headers: {
   "Access-Control-Allow-Origin": "*",
   client_id: process.env.CLIENT_ID,
 },
 baseURL: process.env.API_URL,
});

export default api;

In this file we basically created the initial configuration to use Axios in the application.

Now, let’s create an interceptor for the Responses we’ll receive from the API within this file, something like this:

import axios from "axios";

const api = axios.create({
 headers: {
   "Access-Control-Allow-Origin": "*",
   client_id: process.env.CLIENT_ID,
 },
 baseURL: process.env.API_URL,
});

api.interceptors.response.use(
 (response) => {
   return response;
 },
 async function (error) {
   const access_token = localStorage.getItem("access_token");
   if (error.response.status === 401 && access_token) {
     const response = await refreshToken(error);
     return response;
   }
   return Promise.reject(error);
 }
);

export default api;

We created an interceptor using the api constant, checked if the error status returned by the API was 401, and if the user has an access_token. Then we call the refreshToken() function that we’ll create now:

async function refreshToken(error) {
 return new Promise((resolve, reject) => {
   try {
     const refresh_token = localStorage.getItem("refresh_token");
     const header = {
       "Content-Type": "application/json",
       Authorization: process.env.AUTHORIZATION,
     };
     const parameters = {
       method: "POST",
       headers: header,
     };
     const body = {
       grant_type: "refresh_token",
       refresh_token,
     };
     axios
       .post(
         process.env.API_URL + "/refreshtoken",
         body,
         parameters
       )
       .then(async (res) => {
         localStorage.setItem("access_token", res.data.access_token);
         localStorage.setItem("refresh_token", res.data.refresh_token);
         // Do something after refresh token is successful
         return resolve(res);
       })
       .catch((err) => {
         // Do something if refresh token fails
         return reject(error);
       });
   } catch (err) {
     return reject(err);
   }
 });
};

In this function we are making a new call to the End Point responsible for the refresh token, and if it returns success we will create a flow to update the token within our application where the comment is.

If our refresh token request has failed, we can log out the user by adding a function where the comment is on line 30.

And that’s basically it!