mjrussell / redux-auth-wrapper

A React Higher Order Component (HOC) for handling Authentication and Authorization with Routing and Redux
https://mjrussell.github.io/redux-auth-wrapper
MIT License
2.2k stars 241 forks source link

Infinite loop (redirect ) with nesting wrappers #306

Open kouloughli-hemza opened 2 years ago

kouloughli-hemza commented 2 years ago

Hello , i was trying to implement the exemple of nesting wrappers for auth & admin at the same time , but if user not admin it redirect and keep redirecting untill app freezes;im not sure what was the mistake, is it with asyncComponent ? for admin users it works fine ! only if user is not admin PS: im using ConnectedRouter from connected-react-router Here is my route file :


import React from 'react'
import { Route, Switch } from 'react-router-dom'

import asyncComponent from 'util/asyncComponent'

const App = ({ match }) => (
  <div className="gx-main-content-wrapper">
    <Switch>
      <Route
        path="/unauthorized"
        exact
        component={asyncComponent(() => import('../components/Test/Errors/MissingRole'))}
      />
      <Route
        path="/dashboard"
        exact
        component={asyncComponent(() => import('../containers/Test/Dashboard/Dashboard'))}
      />)
......Long route list

here the wrappers file :


import { connectedRouterRedirect } from 'redux-auth-wrapper/history4/redirect'

import connectedAuthWrapper from 'redux-auth-wrapper/connectedAuthWrapper'
import { push, replace } from 'connected-react-router'
import { compose } from 'redux'
import { DASHBOARD_PATH, SIGNIN_PATH } from './constants/RouteNames'
import { DASHBOARD_ALLOWED_ROLES_IDS } from './constants/Roles'

const userIsAuthenticatedDefaults = {
  authenticatedSelector: (state) => state.auth.token !== null,
  wrapperDisplayName: 'UserIsAuthenticated',
}

export const userIsAuthenticated = connectedAuthWrapper(userIsAuthenticatedDefaults)

export const userIsAuthenticatedRedir = connectedRouterRedirect({
  ...userIsAuthenticatedDefaults,
  redirectPath: SIGNIN_PATH,
  redirectAction: replace,
})

const userIsNotAuthenticatedDefaults = {
  // Want to redirect the user when they are done loading and authenticated
  authenticatedSelector: (state) => state.auth.token === null,
  wrapperDisplayName: 'UserIsNotAuthenticated',
}

export const userIsNotAuthenticated = connectedAuthWrapper(userIsNotAuthenticatedDefaults)

export const userIsNotAuthenticatedRedir = connectedRouterRedirect({
  ...userIsNotAuthenticatedDefaults,
  redirectPath: DASHBOARD_PATH,
  allowRedirectBack: false,
  redirectAction: push,
})

export const userIsNotSuperAdminRedir = connectedRouterRedirect({
  // Want to redirect the user when they are done loading and authenticated
  authenticatedSelector: (state) =>
    state.auth.authUser !== null &&
    DASHBOARD_ALLOWED_ROLES_IDS.includes(state.auth?.authUser?.role_id),
  wrapperDisplayName: 'UserIsAdmin',
  predicate: () => false,
  redirectPath: '/unauthorized',
  allowRedirectBack: false,
  redirectAction: replace,
})

export const userAuthAndAdminChain = compose(userIsAuthenticatedRedir, userIsNotSuperAdminRedir)

here implementation


  // Need to apply the hocs here to avoid applying them inside the render method
  const Login = userIsNotAuthenticatedRedir(SignIn)
  const RestrictedRoute = userIsAuthenticatedRedir(userIsNotSuperAdminRedir(MainApp))

Here my route switch


        <Switch>
          <Route exact path={SIGNIN_PATH} component={Login} />
          <Route path={`${match.url}`} location={location} component={RestrictedRoute} />
        </Switch>

I Hope you can help me spot the mistake

mjrussell commented 2 years ago

Sorry for the late reply, I'm not really actively maintaining this repo at the moment. I dont see anything obviously wrong in what you are doing though. The typical mistake is creating the redirect wrapper inside a function component or something like that which you aren't doing here.