Redux state persistence with a database
Asked Answered
S

2

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.

Suzetta answered 16/11, 2015 at 0:2 Comment(0)
E
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.

Eby answered 16/11, 2015 at 20:31 Comment(1)
This helps immensely - thank you for the articulate response!Suzetta
O
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.

Oneeyed answered 16/11, 2015 at 3:47 Comment(6)
Thanks for the clarification. Would it make sense to store user credentials in the database?Suzetta
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.Oneeyed
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 storageWester
@Martin Oversight on my part regarding XSS vulnerability. But how would you access cross-domain localStorage?Oneeyed
@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, but bottom line is storing authentication data in local storage (or any sensitive information) is generally frowned upon by security folksWester
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 auditWester

© 2022 - 2024 — McMap. All rights reserved.