Login and Authenticated Sections to React/React-Native App

Most single page apps are likely to have some authenticated sections that should be inaccessible unless the user has identified itself. Adding authentication can be a non-trivial challenge for any app and though it’s not very difficult, there are several possible ways to approach this.

The most obvious and the arguably one that offers best security is to have the authentication separated from the app. But this either requires maintaining two different versions of the app for the authenticated and non-authenticated sections or requires server-side page flows. However, this is not always possible, for example when you want to have an installed app that needs to work offline.

This post describes an architecture using React, react-router to handle login and authenticated sections of an app.

With React Router, Route is just a component, just like div. So it is possible to nest multiple routes inside another Route as if it was a div. This makes it really simple to abstract all our authentication logic to one component that could allow/disallow the users to access all nested sections.

This means that you can layout your app like this

<App>
  <Switch>
    <Route path="/login" component={LoginPage} />
    <AuthenticatedRoutes />
  </Switch>
</App>

Simple enough, right?

It’s also really easy to implement the AuthenticatedRoutes component to redirect to login in case the user tries to access one of the nested pages. All of it can fit in 30 lines:

class AuthenticatedRoutes extends Component {
  componentDidMount() {
    const { isLoggedIn, redirectToLogin } = this.props;
    if (!isLoggedIn) {
      redirectToLogin();
    }
  }

  render() {
    const { isLoggedIn, sidebar } = this.props;
    if (isLoggedIn) {
      return (
        <div>
          <Header />
          <Sidebar />
          <section className="content">
            <Route path="/" exact component={IndexPage} />
            <Route path="/route1" exact component={Route1Page} />
            <Route path="/route2">
              <div>
                <Route path="/route2/nested1" component={Route2Nested1Page} />
              </div>
            </Route>
          </section>
        </div>
      );
    }
    return null;
  }
}

This will take care of redirecting to login each time this component is mounted when the user is not logged in. The redirectToLogin action takes care of this and again, it is very simple to write:

export function redirectToLogin() {
  return (dispatch: (action: actionType) => void) => {
    dispatch(push('/login'));
  };
}

The dynamic route philosophy from react router makes laying out the authentication logic really simple and is very easy to understand with most of the logic in a single component.

Published 12 Nov 2017

I build mobile and web applications. Full Stack, Rails, React, Typescript, Kotlin, Swift
Pulkit Goyal on Twitter