James
James

Reputation: 451

Is it safe to store JWT token in redux store?

I am working on one project but I am wondering that if I am already using redux in our application then can we stop using httponly cookie to store token ?

This is my reducer and I am storing the token this way in my reducer. And I am also using redux-persist to persist the user whenever he reload the page.

So, it advisable to store the jwt token like this ?

import * as types from "./user.types";

const initialState = {
  token: null,
  user: {},
  loading: false,
  error: null,
};

const authReducer = (state = initialState, action) => {
  switch (action.type) {
    case types.LOGIN_START:
      return {
        ...state,
        loading: true,
      };
    case types.LOGIN_SUCCESS:
      return {
        ...state,
        loading: false,
        token: action.payload.jwt,
        user: action.payload.user,
      };
    case types.LOGIN_FAIL:
      return {
        ...state,
        loading: false,
        error: action.payload,
      };
    default:
      return state;
  }
};

export default authReducer;

Upvotes: 2

Views: 10646

Answers (3)

Gautam Arora
Gautam Arora

Reputation: 43

You should never store JWT tokens inside your localStorage since they are vulnerable to client side attacks like XSS or CSRF attacks.

Upvotes: 0

sathya reddy
sathya reddy

Reputation: 777

You can keep it in the store and you should also set a timeout for the token expiration that will logout the user once token expires. I have added a package that let's you decode a token to retrieve exp expiration time of the token and you can change it to work with redux-persist

import jwt_decode from "jwt-decode";

const token = localStorage.getItem('token')

const initialState = {
  token: null,
  user: {},
  loading: false,
  error: null,
};

if(token) {
  try {
    const jwt_decoded = jwt_decode(token)
    const timeToExpire = jwt_decoded.exp - Date.now()
    if(timeToExpire > 0) {
      setTimeout(() => {
        // dispatch action to logout
      }, timeToExpire);
      initialState.token = token;
    } 
  } catch (error) {
    console.log("error parsing token")
  }
}

const authReducer = (state = initialState, action) => {
 // your reducer code here
};

Note: There is actually no need to store it in the redux store, instead save to localStorage and where needed you can just read from storage and pass it.

Upvotes: 5

Kumar Saurabh
Kumar Saurabh

Reputation: 366

This way you have to send login request with every refresh as with every page reload redux store reload also.

Better you should save the token in local storage and pull in redux store as initial value so it automatically save with every reload.

In Store:

import { applyMiddleware, combineReducers, compose, createStore } from "redux";
const composeEnhancer = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;  //for redux extension

        const initialState = {
            token: {
            token: localStorage.getItem("token")
              ? JSON.parse(localStorage.getItem("token"))
              : null,
          },
        };
    
    const store = createStore(
      reducer,
      initialState,
      composeEnhancer(applyMiddleware(thunk))
    );

Upvotes: 1

Related Questions