Состояние аутентификации на основе Persist React Cook ie - PullRequest
0 голосов
/ 28 мая 2020

Я создаю поток аутентификации с помощью React-Router и Redux, где мой бэкэнд возвращает JWT в виде Session Cook ie (с HTTP-заголовком Set-Cook ie), который Frontend использует по порядку сделать последующие запросы. (Я не использую localStorage, поскольку общая рекомендация - предпочесть Cook ie из-за риска того, что JS может его прочитать в случае XSS)

// my App component
  const { isAuthenticated } = useSelector((state) => state.user);

          <Container>
            {!isAuthenticated ? (
              <LoginForm />
            ) : (
              <Switch>
                <Route exact path="/" component={MessageList} />
                <Route path="/messages" component={MessageList} />
                <Route path="/login" component={LoginForm} />
                <Route path="/message/:id" component={MessageContainer} />
              </Switch>
            )}
          </Container>
// the api requests themselves abstracted
const login = (data) =>
  axios
    .post("auth/login", data, { withCredentials: true })
    .then((response) => response.data);

const fetchItems = (page, token) =>
  axios(`message/list/page/${page}`, {
    withCredentials: true,
  }).then((response) => response.data);
// actions
function handleError(err) {
  return {
    type: "ERROR_OCCURED",
    payload: err,
  };
}

function shouldFetchMessages(state, page) {
  if (!state.message.all.length) {
    return true;
  } else if (state.message.isFetching) {
    return false;
  } else {
    return state.message.all;
  }
}

export let getMessages = (page = 1) => async (dispatch, getState) => {
  let err, response;

  dispatch(requestMessages(page));
  [err, response] = await to(api.fetchItems(page, getState().user.accessToken));
  if (err) {
    return handleError(err);
  }
  return dispatch(receiveMessages(response));
};

export function getMessagesIfNeeded(page) {
  return (dispatch, getState) => {
    if (shouldFetchMessages(getState(), page)) {
      return dispatch(getMessages(page));
    }
  };
}
// reducer
// where would the localStorage isAuthenticated value be synced with the store?
export default (state = defaultState, action) => {
  switch (action.type) {
    // skipped the other reducers for brevity
    case "ERROR_OCCURED":
      return {
        ...state,
        isAuthenticated: false, // this should be saved in the localStorage
      };
    default:
      return state;
  }
};

Мне нужен BOOLEAN, который хранит "состояние" isAuthenticated, чтобы я мог показать соответствующий компонент.

Моя основная проблема в том, что состояние Redux, конечно, не сохраняется при обновлении страниц.

Я думал о наличии переменной localStorage (или новой cookie). (Cook ie, который содержит JWT, - это httpOnly и, насколько я понимаю, не может быть доступен JavaScript).

Вопросы:

  • это устоявшаяся практика
  • как будет обрабатываться истечение срока действия JWT? (Думаю, я мог бы установить для него значение false, если HTTP-запрос завершится с ошибкой с 401.)
  • где будет синхронизироваться переменная localStorage с состоянием Redux, чтобы избежать побочных эффектов в моих редукторах?
...