19

From the discussion here it seems that the state of Redux reducers should be persisted in a database.

How does something like user authentication works in this instance?

Wouldn't a new state object be created to replace the previous state in the database for every user (and their application state) created and edited?

Would using all of this data on the front end and constantly updating the state in the database be performant?

Edit: I've created an example Redux auth project that also happens to exemplify universal Redux, and realtime updating with Redux, Socket.io and RethinkDB.

Community
  • 1
  • 1
hoodsy
  • 824
  • 2
  • 11
  • 18

2 Answers2

30

From the discussion here it seems that the state of Redux reducers should be persisted in a database.

To persist the state or not, it's likely not a concern of Redux at all. It's more up to application logic.

If something happens in an application, like data upload to server, obviously you need to save state (or a slice of the state to a server).

Since network calls are asynchronous, but Redux is synchronous - you need to introduce additional middleware, as redux-thunk or redux-promise.

As sign-up example, you likely need that actions,

export function creatingAccount() {
  return { type: 'CREATING_ACCOUNT' };
}

export function accountCreated(account) {
  return { type: 'ACCOUNT_CREATED', payload: account };
}

export function accountCreatingFailed(error) {
  return { type: 'ACCOUNT_CREATING_FAILED', payload: error };
}

export function createAccount(data, redirectParam) {
  return (dispatch) => {
    dispatch(creatingAccount());

    const url = config.apiUrl + '/auth/signup';

    fetch(url).post({ body: data })
      .then(account => {
        dispatch(accountCreated(account));
      })
      .catch(err => {
        dispatch(accountCreatingFailed(err));
      });
  };
}

Some portion of state, e.g. user object after authorization, might be stored to localStore and re-hydrated on next application run.

Andrew Hedges
  • 21,058
  • 16
  • 62
  • 78
Alexander Beletsky
  • 18,109
  • 9
  • 57
  • 84
9

Those are valid concerns. Using localStorage to persist state on the frontend might be a better strategy. You can implement this using middleware, for example:

import {createStore, compose, applyMiddleware} from 'redux';

const localStorageMiddleware = ({getState}) => {
  return (next) => (action) => {
    const result = next(action);
    localStorage.setItem('applicationState', JSON.stringify(
      getState()
    ));
    return result;
  };
};

const store = compose(
  applyMiddleware(
    localStorageMiddleware
  )
)(createStore)(
  reducer,
  JSON.parse(localStorage.getItem('applicationState'))
)

If you're concerned about the enemy accessing the user's laptop and stealing credentials from it you could persist state to the backend when the user leaves the page (Navigator.sendBeacon() might be helpful here) & store it in the session.

Ashton Six
  • 433
  • 4
  • 18
  • Thanks for the clarification. Would it make sense to store user credentials in the database? – hoodsy Nov 17 '15 at 00:57
  • Absolutely! You'd still want to store information on the backend, `localStorage` is transient and you shouldn't assume data will last more than 30 days there. The use cases for `localStorage` include storing auth tokens, the current page, data loaded from the backend (to avoid reloads). Redux state contains a lot of these which is why rehydrating it between page loads makes sense. Storing data on the backend is often nescersary, sometimes a different approach makes more sense. – Ashton Six Nov 17 '15 at 17:12
  • 2
    local storage should **never** be used for storing authentication information as it is very vulnerable to XSS attacks => local storage is not domain-specific so an attacker doesn't even have to inject a script into your site to access it - they can simply get an unwitting victim to go to `{$someEvilDomain}.com` and then run a script from there that grabs **everything** in local storage – Jordan Jan 31 '16 at 17:02
  • 1
    @Martin Oversight on my part regarding XSS vulnerability. But how would you access cross-domain localStorage? – Ashton Six Feb 01 '16 at 18:19
  • 1
    @AshtonWar - actually my recollection was incorrect - you can't enumerate all keys across all domains, but you can target specific domains via some [iFrame sourcery](https://www.nczonline.net/blog/2010/09/07/learning-from-xauth-cross-domain-localstorage/), but bottom line is storing authentication data in local storage (or any sensitive information) is generally frowned upon by security folks – Jordan Feb 01 '16 at 20:43
  • Also worth noting that some folks try to get around this limitation by storing auth data on the client in an encrypted form, but I can tell you from personal experience that this probably won't survive a security audit – Jordan Feb 02 '16 at 15:34