Sitemap
All things #search

A blog about building search UIs and apps with ReactiveSearch. For Elasticsearch, OpenSearch, Solr and MongoDB search engines

Follow publication

How to Implement Authentication For Your React App

--

Image: Using Auth0 for building an authentication flow for a client-side react app.

A good authentication system is a crucial ingredient for building modern apps, and also one of the most common challenges that app developers face.

There are several contributing factors that make designing good authentication flows a challenge. For instance, OAuth flows work ever slightly so differently across providers. And handling a client-side only flow is quite different than a middleware based flow. Further, there are different kinds of authentication flows: sometimes, you may want a passwordless authentication and other times, you may want an old-school username and password based flow. And once you have implemented an auth flow, handling user authorizations is an altogether different challenge.

In this tutorial, I will walk through building an Authentication flow for a client-only React app with a very simple authorization rule:

  • Display a database connected UI view that is only visible to logged in users. I will be using ReactiveSearch for building this quickly, but the walk through should apply the same for any React view.
  • I will be using Auth0 to implement the authentication flow that will support logging in either via an e-mail / password mechanism or a Google OAuth login.

Here is how the final app will look like:

Try out the live app by clicking here.

When is it a good Idea to Implement Authentication

Before we dive deeper, it is always a good exercise to think if your app really needs an authentication flow.

If your site or app data is public, and you don’t care about resource abuse and DoS attacks in particular, it is fine to do away with an authentication flow.

In all other scenarios, you would at least want a part of your UI view to implement authentication. May be, it is the admin dashboard or may be it is the ability to post data or perhaps it is a mechanism to associate a public profile for encouraging sane user conversations.

Basics: An Authentication Token

I want to start by introducing the idea of an authentication token. An authentication (or access) token is a piece of data sent by a server to a client when the user authenticates herself or himself with the correct credentials.

A token improves the future accessibility of the app where the user doesn’t have to go through the authentication flow every single time s/he is trying to do something with the app. A good practice is to apply a time limit (like 14 days or 30 days) on a token so as to get an optimal trade-off between ease of use and security. Depending on what kind of app you are building, this can be as low as a few minutes to sometimes as long as several months.

OAuth tokens are used by a lot of apps for authentication. When we signup or login via Auth0 we’ll receive an id_token (containing user’s profile information)and an access_token (a credential that can be used by a client to access an API). We’ll store these tokens on our client for future use.

The Set Up

We will start by signing up for the Auth0 service, and create a new client for our tutorial app. We’ll need the Client ID and Domain in order to configure auth0 in our app. You can get these from your Auth0 dashboard.

Press enter or click to view image in full size
Image: Getting the Domain and Client ID from Auth0 Dashboard (my client is called reactivesearch-auth0)

We’ll also need to add a callback URL in the Allowed Callback URLs section since after authentication the client is redirected back to the callback URL with the token info which we’ll later parse for our use. You can add the following to the Allowed Callback URLs:

http://localhost:3000/callback   // our app will run on 3000 port
http://yourhosteddomain:PORT // add if you are hosting it live
Press enter or click to view image in full size
Image: Adding allowed callback URLs in Auth0 Dashboard

Building the React App

This is how our final app’s file structure will look.

├── public
│ ├── 404.html // used for handling routes on gh-pages
│ └── index.html // root index html
└── src
├── App.js // reactivesearch example app
├── auth.js // main authentication service for our app
├── Callback.js // displayed when auth0 redirects to callback URL
├── history.js // used by auth service and react-router
├── Home.js // the root component for final app
├── index.css // styles
├── index.js // renders the final app using ReactDOM
└── Routes.js // uses react-router to handle all the app routes

1. Initializing the React project

I’m using create-react-app to set up the project easily without manually adding configurations:

npm install -g create-react-app // if you don't already have itcreate-react-app reactivesearch-auth0-example

After the dependencies are installed you can cd into the reactivesearch-auth0-example directory and run:

npm start

which should start the project at http://localhost:3000/.

Press enter or click to view image in full size
Image: CRA welcome screen (you should be seeing something like this)

2. Adding ReactiveSearch: Our UI View

Now that we have the basic react app initialized, lets create our UI view. We will use ReactiveSearch for building a quick UI.

npm install @appbaseio/reactivesearch

After adding the reactivesearch dependency we have to include reactivesearch styles into the build system. A simple way to do is to import the reactivesearch styles in our root project file src/index.js. This will inform webpack to bundle the CSS for reactivesearch along with the project.

import '@appbaseio/reactivesearch/dist/css/style.min.css';

We will use materialize as the style framework and add the CDN link directly in the /public/index.html file.

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.98.0/css/materialize.min.css">

We can import some basic components in /src/App.js as:

import {
ReactiveBase,
CategorySearch,
RatingsFilter,
ResultCard
} from '@appbaseio/reactivesearch';

3. Getting started with ReactiveSearch

To start with, we will create a simple application with a few components. Alternatively, you can also follow these links to create your own app with your data:

(i) Creating an app and importing data

(ii) Understanding the base component for reactivesearch

The sample app we’re building is taken from the reactivesearch quick start guide. Lets modify the src/App.js file in our project directory. The final app should look like this:

Setting up the reactivesearch example app

If you have followed along thus far, the project should now look like this:

Press enter or click to view image in full size
Image: Our React App after adding ReactiveSearch

Now that our React app is up and running with a live data view, lets proceed with adding authentication. You can also get the final code from the project repository.

Adding Authentication

When built, our app’s authentication flow will look like this:

Your App → Auth0 login → Auth0 authenticates user → Auth0 redirects to callback URL → Your App with the token

Image: Authentication flow

You can also check out the following screen-cast to see it in action:

Authentication flow

We’ll be following the Auth0 quick start guide for adding authentication to our React app, with some modifications to suit our app’s purpose.

1. Adding Auth0 and React Router

You can install auth0-js dependency by running:

npm install auth0-js

We’ll also need react-router-dom to handle the routes:

npm install react-router-dom

2. Creating An Authentication Service

We’ll be creating a history service to easily manipulate browser history. We’ll use history package which will be used by the authentication service and react-router.

createHistory can also accept an object containing basename property. This can be helpful if you want to set a base URL for all the routes. We’ll use the same history with react-router to correctly handle routes on our app deployed at github pages. In development we don’t need any such base URL.

Creating browser history service

We’ll be adding an authentication service to use auth0-js. This will look like:

Creating authentication service

Here’s how the authentication service works in a nutshell:

  • auth0 is a new instance of the Auth0 client. The redirectUri is set to localhost in development and to the project domain otherwise (which is github pages for this project)
  • login method calls the authorize method on the auth0 client which will open up the Auth0 login screen.
  • handleAuthentication method calls the parseHash method on the auth0 client. We’ll call this after successful authentication to read the token information from the page URL Auth0 redirects to after authentication.
  • setSession stores the information about access_token, id_token and expires_at in local storage so we can use it later without going through the authentication process again.
  • logout clears all the session information about the tokens and expiry time from the local storage. After logout the user will need to authenticate (login) again to get the tokens.
  • isAuthenticated checks if the token is past expiry time (set at the time of login). If the token is expired, the user will have to authenticate again and get a fresh set of tokens.

3. Adding a Callback component

We’ll need a Callback component to handle redirects from auth0. This component will show a loading message till the session is set up. After this the user will be redirected to the UI view by the authentication service.

Creating Callback component to handle redirects from Auth0

4. Adding a Home component

App component (the one we created previously) only if the user is logged in using our authentication.

  • We will show an example view to a non-authenticated user with an option to login or signup.
Creating Home component to conditionally render App

The Home component calls the isAuthenticated method in authentication service /src/auth.js and displays the App component only if the user is authenticated.

5. Setting up app routes and handling authentication

We’ll be using react-router-dom from react-router to handle all our routes. The handleAuthentication method is called after Callback component is rendered and parses the URL hash from the page auth0 redirects to after authentication. After we extract the token information we will direct the user to the Home component.

Creating Routes

The Router component takes the same history object that we used earlier in /src/auth.js. We’ve set simple routes:

  • / route is the main route which renders the Home component
  • /home route also renders the Home component. This is the same route the user is redirected to after authentication.
  • /callback route renders the Callback component and runs the handleAuthentication function to parse the token information from Auth0’s redirect URL.

All the components rendered by react-router are also passed the auth object as a prop and all the other props by Route as {…props}. We don’t need the additional props from react-router in this tutorial but they’re very helpful when you want to interact with the history.

We have to also update the root component in /src/index.js to render the Routes component instead of the App component.

Updating the root component in index.js

That’s it! Our app is now ready with an authentication flow. You can now have fun with tweaking the UI view and adding more complex authorization views.

Further Reading

Check out the followup post on adding authentication to your APIs:

Summary

We walked through building a client-side only authentication flow for a React app. In the process, we learnt about the idea of access tokens and how they form the centerpiece of any authentication flow, and built a flow where we support username / password and Google based logins.

If you liked this post, you will love our deep dive posts for building data-driven Reactive Apps:

Learn how to build reactive apps — one post at a time!

--

--

All things #search
All things #search

A blog about building search UIs and apps with ReactiveSearch. For Elasticsearch, OpenSearch, Solr and MongoDB search engines

Divyanshu Maithani
Divyanshu Maithani

Life, music, code and things in between…

Responses (2)