Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I store a JWT in cookies using Axios?

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?

like image 479
G. Cox Avatar asked Feb 12 '19 14:02

G. Cox


People also ask

Can JWT be stored in cookie?

To keep them secure, you should always store JWTs inside an httpOnly cookie. This is a special kind of cookie that's only sent in HTTP requests to the server. It's never accessible (both for reading or writing) from JavaScript running in the browser.

How do I store JWT in cookie react?

JWT in CookieA cookie can be set from the server-side and also in client-side, First we can see how to set and get the JWT from the cookie in the React and using the browser console. The cookie is set to the current domain by default and expiry date is set to 1st Jan 2021.

How do I store JWT Inside an httpOnly cookie?

HTTP Only JWT Cookie: In a SPA(Single Page Application) Authentication JWT token either can be stored in browser 'LocalStorage' or in 'Cookie'. Storing JWT token inside of the cookie then the cookie should be HTTP Only. The HTTP-Only cookie nature is that it will be only accessible by the server application.


1 Answers

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.

like image 131
Pas Avatar answered Oct 12 '22 14:10

Pas