1

Almost every blog post I've encountered around generic auth handling using JWTs in a React/Redux/Saga application does the same thing, which is to store the JWT in local storage, in the action/saga.

For example:

Example A (redux-saga):

function* authorize({ payload: { login, password } }) {
  const options = {
    body: JSON.stringify({ login, password }),
    method: 'POST',
    headers: { 'Content-Type': 'application/json' }
  };

  try {
    const { token } = yield call(fetchJSON, '/login', options);
    yield put({ type: AUTH_SUCCESS, payload: token });
    localStorage.setItem('token', token);
  } catch (error) {
    let message;
    switch (error.status) {
      case 500: message = 'Internal Server Error'; break;
      case 401: message = 'Invalid credentials'; break;
      default: message = 'Something went wrong';
    }
    yield put({ type: AUTH_FAILURE, payload: message });
    localStorage.removeItem('token');
  }
}

function* Saga() {
  yield takeLatest(AUTH_REQUEST, authorize);
}

Example B (redux):

function login(username, password) {
    const requestOptions = {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ username, password })
    };

    return fetch(`${config.apiUrl}/users/authenticate`, requestOptions)
        .then(handleResponse)
        .then(user => {
            // login successful if there's a jwt token in the response
            if (user.token) {
                // store user details and jwt token in local storage to keep user logged in between page refreshes
                localStorage.setItem('user', JSON.stringify(user));
            }

            return user;
        });
}

function logout() {
    // remove user from local storage to log user out
    localStorage.removeItem('user');
}

Now - storing JWTs in local storage aside - what concerns me - is the setting of state inside of the action creator/saga - rather than in a reducer.

My understanding is that action creators/sagas should be used just to determine the data to be used - and it is up to the reducers to actual store/persist the data.

Now of course - at its initial state, redux won't persist data. However, you can use a redux middleware like redux-persist to persist it to local storage (and there are other redux-persist middlewares to persist data to other places). Point here is - redux is the state management.

Why then - does everybody seem to just sidestep using redux as your application state when it comes to authentication?

2

I will do a guess from different sources.

  1. I heard "security is not a crosscutting concern" I would put authentication in it. It can not be separated from the program although not included in the model and then pressed in when needed.
  2. Whether you are authenticated is not part of your model in a way that you have two objects, one authenticated and one not authenticated at the same time.

Thus, you try to push authentication as far away from the other logic. You put it in a layer between communication and model. That layer is so thin that you do not give extra space to it in an example as this layer may not evolve or evolve in unforeseen ways in programs building on the example. Besides, there are only two places to handle that use case.

An other one is that in an example, you like to go for simplicity instead of perfection.

PS: An answer like this usually leads to better answers coming. Good luck!

2

For me the main reason to store the token in local storage instead of redux store is that they are fundamentally different in nature in that:

  • You usually want too keep the auth token between page refreshes
  • You may want or not to do that with the application state

Aside from that, setting the state in the action creator seems to me just wrong, since the sole responsibility of those should be returning the action.

Setting local storage is by definition a side effect so it seems to me that the logical place is in your side effects handler of choice - in many cases the sagas.

  • Right but if you're using redux persist you can persist the application state, or choose which ones to persist. I should update the question. – dwjohnston Dec 7 '18 at 21:37
  • Yes, and that makes sense, but most people are not using redux persist. At least not when talking or creating tutorials for auth. It does not mean that it is not better to actually store the token in redux and let redux persist manage persistence, but it explains why usually you don't see it done like that – Tiago Coelho Dec 7 '18 at 22:16
  • One minor distinction: reducers don't persist data, they just compute new states from previous state and action. Redux persist is a store enhancer – Tiago Coelho Dec 7 '18 at 22:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.