theNotSoPro
theNotSoPro

Reputation: 318

React routing and private routes

I'm trying to block access to private paths by checking with my express server if a user has logged in prior to allowing access to it, otherwise redirect to login.

I created a private route function that checks with the server. Problem is, i don't know how to get it to wait for the response before deciding which component to route to (private page vs login).

const isAuthed = () => {
  fetch('/api/checkLogin', {
    method: 'GET',
    credentials: 'include'
  })
  .then(response => {
    console.log(response.status == 200);
    return response.status == 200;
  });
}

const PrivateRoute = ({ component: Component, ...rest }) => {
    return (
      <Route
        {...rest}
        render={props =>
          isAuthed() == true ? (
            <Component {...props} />
          ) : (
            <Redirect
              to={{
                pathname: "/login",
                state: { from: props.location }
              }}
            />
          )
        }
      />
    );
  }

This is always Redirecting to login...

Any ideas?

EDIT 1 Here's how PrivateRoute is being used.

const Routing = (props) => (
  <div>
    <Switch>
      <Route exact path='/' component={Home} />
      <PrivateRoute exact path='/profile' component={Profile} />
      <PrivateRoute exact path='/auction_list' component={Auctions} />
    </Switch>
  </div>
)

With react, seems like I have to return something when calling for the Routing component. I can't async call to PrivateRoute then have that async call give a return update.

EDIT 2 I tried using react-redux to store the login data so I don't have to do an async call to the server to auth. However, refreshing the page would wipe out all redux storage so it's as if the user is not logged in after refresh, that's pretty clunky.

I thought of putting the info in session storage. But user won't be able to log out of all machines at once.

I ended up pinging the server from componentWillMount of each of the private components. The private page might flash for a fraction of a second but that's the best I can do so far...Let me know if there's a better way...there must be one.

Upvotes: 1

Views: 3723

Answers (2)

zootechdrum
zootechdrum

Reputation: 111

Letting the user access private routes seems so weird to me. Even if it is just the view. I get they wont have access to any actions when it comes to the database, but it still seems like a flaw. I was also trying to check with the server on every request on my protected route and ended up at this same exact issue. The only way to get around this is to have the actual screen/page make the call and validate the JWT token. I think in my case this will be enough.

Upvotes: 0

Roy Wang
Roy Wang

Reputation: 11260

You should not be authenticating through the server every time the user visits the site.

react-router's conditional routing only works if the condition can be checked synchronously.

When the user successfully authenticated for the first time, you store a variable indicating the authentication status (with an expiry date if desired) to localStorage.

When the user visits the website again, you will be able to redirect by getting the auth status from localStorage (which is a synchronous operation).

Upvotes: 1

Related Questions