8

How can I ensure only logged in user to be able to access to home and task page? I'm using redux and I try to avoid any pre-made auth component to learn better about auth.

const App = props => (
    <BrowserRouter>
        <Provider store={store}>
            <div className="app">
                <Layout>
                <Header>
                    <Navbar />
                </Header>
                <Content>
                    <Route exact path='/' component={Home} />
                    <Route exact path='/login' component={Login} />
                    <Route exact path='/signup' component={Signup} />
                    <Route exact path='/task/:id' component={Task} />
                </Content>
                </Layout>
            </div>
        </Provider>
    </BrowserRouter>
)

I was using angular and there's middleware concept in route, but in react I'm lost. I think auth has nothing to do with redux's store? do I need to call to get the user detail's from api when the user navigate around the app?

Jenny Mok
  • 2,744
  • 9
  • 27
  • 58

1 Answers1

6

To solve this problem in our application, we used a higher order component and wrapped our root application route use it. Our route structure was a bit different, but for any route you need "protected" you could use the same concept.

The higher order component just "extends" a component's functionality. Redux's connect is a HOC. In this case, the extended functionality would be checking for authentication. When the component mounts, you'd want to make your check for authentication, whether checking a server or localStorage, etc. Build a new component file like so:

import React from 'react'

export default function(ComposedComponent) {

  class RequireAuth extends Component {

    state = {
      isAuthenticated: false
    }

    // Push to login route if not authenticated on mount
    componentWillMount() {
      if(!this.state.authenticated) {
        // Use your router to redirect them to login page
      }
    }

    // Push to login route if not authenticated on update
    componentWillUpdate(nextProps) {
      if(!this.state.authenticated) {
        // Use your router to redirect them to login page
      }
    }

    // Otherwise render the original component
    render() {
      return <ComposedComponent {...this.props}/>
    }

  }

  return RequireAuth

}

In your routes file, just import the HOC as RequireAuth or something similar, and use like so:

<Route exact path='/' component={RequireAuth(Home)} />

This more or less does the following: When your router hits the home route, it runs the RequireAuth check when it attempts to render the route component. The RequireAuth will need to check for some sort of authentication you set up, and set the isAuthenticated state to true. If it's not true, it should redirect to your login route or something similar. You can also connect this HOC to redux to save that isAuthenticated state to the store instead of component state.

Tom Nolan
  • 1,916
  • 4
  • 32
  • 51
  • Do I have to call api every time user navigate the app? or I just simply check the user object in localstorage? – Jenny Mok Aug 27 '17 at 13:53
  • I wouldn't call the API every time, no. Just store the authentication state to let them continue using without issue. If you need a more "secure" app, something like a bank that logs you out after X time of inactivity or something, you can setup a function to hit your API again, to check. – Tom Nolan Aug 27 '17 at 13:54
  • We usually only execute the login check `onEnter`ing the route for the first time. Since it's a single page application, it will only fire the check once unless the user refreshes the page. – Tom Nolan Aug 27 '17 at 13:55
  • Great. I got the point but I don't know what to do in my auth component. in my app.js I did this ` ` but what to write in Auth component? – Jenny Mok Aug 27 '17 at 13:56
  • It would really depend on what code you're actually executing to authenticate, where you want to store the state and possibly how redux is configured within your app. What we do, is have a redux action creator for logging in (outside of the HOC), that updates the `isAuthenticated` state in redux after the user logs in using our API. All the HOC then does, is checks whether or not that is `true` or `false` by `connect`ing to redux and takes appropriate action on mount by either redirecting to login or just allowing the user in. – Tom Nolan Aug 27 '17 at 13:59