How can I store a JWT in cookies using Axios?

12,185

There are a few different options that you can take here to solve the problem you are having, which is simply finding somewhere to store the JWT so that you can use it even after you refresh the page.

  1. Save the JWT in localStorage or sessionStorage in your axios.post callback so that you can have access to it even after the page refreshes. To learn which storage is most suitable for your app, see this.

    To keep it short, values stored in localStorage will persist until you explicitly delete them (you can do this via your JS code). Also, any tabs you open in your browser to that domain will have access to this (very useful if you want to still be logged in with the new tabs). On the other hand, values stored in sessionStorage only live until the tab is closed. They can't be shared across tabs either.

    Using this is as simple as:
    localStorage.setItem("JWT", authToken); or sessionStorage.setItem("JWT", authToken); in your callback after your authToken = res.data.token;

    So now that you have a place where you have stored the JWT, all you need to do is make sure to check if a JWT exists in storage when your app initializes on page load (or refresh). Here's a basic example of how to use localStorage:

// This should be one of the first things that run on your app.

const axios = axiosAPI.create({
    baseURL: baseURL
});

// Check if user is logged in.
(function() { 
  let authToken = localStorage.getItem("JWT");
  if (authToken === null) {
      // This means that there ISN'T JWT and no user is logged in.
      axios.defaults.headers.common.Authorization = null;
  } else {
      // This means that there IS a JWT so someone must be logged in.
      axios.defaults.headers.common.Authorization = `Bearer ${authToken}`;
  }
})();

This will make sure that the user is not logged out on page load, if previously logged in.

  1. Save the JWT in a client side cookie. Here, the cookie is being used as a storage mechanism since you are not actually working with server side cookies given that your authentication is all build around JWT. You can follow the same code pattern as above but instead will be using document.cookie = "key=value" to set a cookie and document.cookie to view all cookies.

    This second way is less common because it forces you to do a lot of manual labor like parsing through all the cookies and making sure to set the proper cookie path attribute so that the cookie only gets sent up for the required endpoints (otherwise you're just creating unnecessary overhead). If you exercise this option, read this to help you create your cookie to fit your needs. You can also use a helper JS library like js-cookie to help manipulate client side cookies.

Additionally, I would read through https://stackoverflow.com/a/40376819/11048825 to dive further into these two options and understand the pros and cons associated with each.

Share:
12,185
G. Cox
Author by

G. Cox

Updated on June 14, 2022

Comments

  • G. Cox
    G. Cox almost 2 years

    I am using JWT in my React application and Axios to handle API calls. I am looking for a way to store the token in cookies so that I am not redirected to login again every time the browser is refreshed.

    Here is my setup for Axios and my login call:

    let authToken = null; 
    
    const axios = axiosAPI.create({
        baseURL: baseURL
    });
    
    // User login
    export const loginUser = (data) => {
        return new Promise((resolve, reject) => {
            axios.post(`${baseURL}/jwt-auth/v1/token`, data)
                .then((res) => {
                    authToken = res.data.token;
    
                    // Adds the token to the header
                    axios.defaults.headers.common.Authorization = `Bearer ${authToken}`;
    
                    resolve(res.data);
                })
                .catch((error) => {
                    reject(error);
                });
        });
    };
    

    I am not certain where I should be setting the cookie and how to set it?

    EDIT:

    I have rewritten my code using js-cookie so it looks like the comment.

    import axiosAPI from 'axios';
    import Cookies from 'js-cookie';
    
    let authToken = null;
    
    const axios = axiosAPI.create({
        baseURL: `${baseURL}`
    });
    
    // Check if user is logged in.
    (function () {
        if (Cookies.get('token') === null) {
            // This means that there's no JWT and no user is logged in.
            axios.defaults.headers.common.Authorization = null;
        } else {
            // This means that there's a JWT so someone must be logged in.
            axios.defaults.headers.common.Authorization = `Bearer ${authToken}`;
        }
    }());
    
    // User login
    export const loginUser = (data) => {
        return new Promise((resolve, reject) => {
            axios.post(`${baseURL}/jwt-auth/v1/token`, data)
                .then((res) => {
                    authToken = res.data.token;
    
                    Cookies.setToken('token', authToken);
    
                    // Adds the token to the header
                    axios.defaults.headers.common.Authorization = `Bearer ${authToken}`;
    
                    resolve(res.data);
                })
                .catch((error) => {
                    reject(error);
                });
        });
    };
    

    However this prevents me from logging in at all and I get the error 'wrong number of segments'. Any idea why this isn't working?

  • G. Cox
    G. Cox about 5 years
    Tried using your code and using js-cookie to set and get cookies. I've editing the original post to show my new code. Any idea why it doesn't work?
  • Pas
    Pas about 5 years
    @G.Cox - Ah, I realized I am assigning Bearer ${authToken} to the axois Authorization header on page load when clearly, authToken is not even defined in that anonymous function. I've fixed my mistake above. Make sure you do the same in your code by doing something like let authToken = Cookies.get('token'); before your if/else statement in your anonymous function.
  • Pas
    Pas about 5 years
    @G.Cox - Also, there's another typo in your code. Instead of Cookies.setToken('token', authToken), it should be Cookies.set('token', authToken);
  • dgarcia
    dgarcia over 3 years
    Do not store tokens neither using localStorage nor sessionStorage as they are exposed to JavaScript and hence could be an easy spot to Cross-site scripting attacks.