I love apps that remember who I am and redirects me to certain pages on load, depending on if I’m logged in or not. I read an amazing post about React and Flux Auth Flow. It does an exceptional job at walking through the process of user authentication using React, Flux and React Router…
However, this approach will only work with a pure client side application. I looked tirelessly online for a simple way to authenticate an isomporhic application, but there wasn’t much on subject.
Through playing around, I’ve found my own way to implement a very similar auth flow that works amazing well with server side rendering! The main difference between my implementation and the other ones is that I’ve opted out of using
willTransitionTo, which I’ll explain why at the end.
(For brevity, I will keep my code snippets fairly simple, this is by no means an example of production grade code).
Here’s what we’ll be using:
React Routerfor our routing purposes
Refluxas the flux implementation
Nodeas our backend API
JSON Web Token (JWT)for current user instance storage
localStorageto store our JWTs on the client
In order to create the best user flow, here are a few things we’ll focus on:
- Creating a decorator to protect confidential components from unauthorized users
- If the user was previously logged in, we'll show them their dashboard on app load
- If the user manually changes the route causing a page refresh, we want to auto authenticate them on the new path load
Let’s first set up our example routes:
For simplicity sake, we’ll keep it to a few basic routes.
dashboard will be the only protected route/component in our app, meaning in order to access it, a current user must be present; otherwise we want to redirect the client to the
Creating a decorator to protect confidential components from unauthorized users
In order to shield our
dashboard component from any unauthorized users. We need to wrap it in a custom decorator to make sure that a logged in user is present before revealing it’s contents. We do that like so:
Now whenever we need to protect a component to only authorized users, we simply call it like so:
When a user tries to access this component either through the app’s flow or manually through the URL, they will either be authenticated and saved in state or redirected to a manual login page.
Get or authenticate the current user when a new route is rendered
First, let’s quickly configure the server side render code:
According to our route definitions, the default component a user hits on load is the
HomeHandler. In order for the user to be redirected if logged in, we first must check for an existing current user instance here.
currentUser state exists on the
AuthStore, it means that the loading of the default route was likely triggered programatically, therefore
AuthStore state is persisted and there’s no need to reevaluate the current user.
However, if the route was manually triggered, it would run server-side, meaning no
currentUser state exists on the
AuthStore. In that case we check for a
localStorage and if such a token exists, we use that to call our API and authenticate the user. Here’s our
Once we call
autoLoginUser, it makes an AJAX call to our API to authenticate the
JWT, once the token has been verified, we save the current user data in our state, trigger it and redirect the user to their dashboard.
Here I’ve used
RouterContainer twice, once in my actions and once in my store. Both times, I’ve used it to redirect the user from within Flux.
RouterContainer is just a container for our instance of the the React Router. We set this initally in our client side render like so:
Here’s the file for
Once we’ve set the instance of router in our
RouterContainer, we can reuse it anywhere in our app by calling
RouterContianer.get(), including our Flux actions and stores.
Now when the user tries to access our application, either from the root URL or by manually entering a URL (ie
http://www.myapp.com/dashboard), we can authenticate and either reveal the app content or redirect then to the appropriate page.
Thats it! That’s the very rough and dirty guide to user authentication in an isomorphic React app.
I should mention that if you’re only authenticating a client side app and there’s no server side rendering, you should check out the
willTransitionTo static method on React Router as mentioned in the React Auth Flow blog post I read. The reason why I didn’t use
willTransitionTo is because when we render server side, the state of our stores and
localStorage are both unaccesible, therefore it’s much easier to show a loading screen for a split second while the client authenticates the user directly after the server renders the inital React code.