RecipeMart — A Complete React Application with Auth0 authentication

A React application with BootStrap 4, React JS, React Router, API data and Auth0 Authentication

In this article, we will develop a React application to demonstrate the usage of React JS, React Router DOM. We will finally enable authentication with Auth0.

RecipeMart.com Login Page

Part 1: Application Introduction

Our Application

We are building an application that displays various recipes. Our application, which we branded as RecipeMart.com, expects users to login before they can try our recipes. Once login, users are presented with the categories of recipes. Users can click on an individual category to browse to the list of recipes.

Technology Stack

We are using the following technologies:-

  1. React JS/npm — Powers up our application
  2. Bootstrap 4 — Styling our application
  3. Auth0 — Authenticates our users
  4. https://www.edamam.com/ — API that supplies us the recipes
  5. Visual Studio Code — Text Editor

Part 2: Building the Application

Creating a new React Application

We will use npx create-react-app to create our skeleton react application. Open a terminal/Command Prompt window and execute the following commands. This will create a new react application for us.

npx create-react-app recipemart
cd recipemart

Note that in order to run npx, you need to have node package manager installed. Refer to this link if you don’t have npm on your computer.

Creating React App

Once the app is created, open it with Visual Studio Code editor:-

RecipeMart application in Visual Studio Code Editor

Open a new terminal in the editor and hit npm start. If everything is installed properly, we will see the following welcome page in the browser:-

Initial RecipeMart Application

Adding Bootstrap in the index.html

Let us now add bootstrap in our application’s index.html (public/index.html). Add the following:-

In <head> section:

<link rel=”stylesheet” href=”https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">

<link href=”https://fonts.googleapis.com/css?family=Changa|Tangerine&display=swap" rel=”stylesheet”>

Before end of </body> tag:

<script src=”https://code.jquery.com/jquery-3.3.1.slim.min.js"></script

<script src=”https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>

<script src=”https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>

Also, edit the title to RecipeMart.com. Our final index.html page:-

Add the at the top of App.css file:

body{
font-family: ‘Changa’, sans-serif;
}

Let us edit the App.js as below:-

We would see the following in the browser:-

Creating Header Component

Let’s move on to create our first component. Create a new folder named components under src directory and create a Header.js inside it as below:-

Add this Header component in App.js as below:

<div className=”App”>
<Header />
</div>

Once done, we will see the following in the browser:-

RecipeMart.com with Header Component

Defining Route Links

Now we will install react-router-dom. This will allow us to define our route links. Browse to the terminal window and hit the following command:-

npm install react-router-dom

Let us now create the links. We will have the following links:-

/ → Home Page
/about → About Page
/callback → Callback Page used by Auth0
/notFound → Invalid Links
/recipes → Recipes
/loginFailed → Invalid Login

Update the App.js file as below:

Let us now create the components:-

Main.js (inside src/components)

Main.css (inside src/components)

Main.css

Callback.js (inside src/components)

Below is the empty Callback component. This component we will use later when we will add authentication in our application.

Callback.js

Recipes.js (inside src/components)

Below is the empty Recipes component. This will be our primary component to provide all the recipes.

Recipes.js

We will finally see the following page:-

http://localhost:3000

http://localhost:3000/about

About Page

This ensures that our Router is working as expected.

Before proceeding further, let us understand two different types of components — Functional and Class-based. Functional components are the dumb components as these only paint the UI component they are representing. Whereas, Class-based components are used for application state management.

Building the Recipe component

The recipe is the primary component in our application. It renders two sets of data. Initially, it displays all recipe categories. Later on, based on user action, it re-renders the list of recipes of the specific category. We use two flags — displayCategories and displayRecipies to achieve this. displayCategories is set to true initially, hence it displays the categories and displayRecipies is set to false, hence it does not render the specific category of recipes. recipes variable holds formatted recipe data.

Recipes.js initial state

We are using images to display our categories. All images can be found here (Image Courtesy: Google Images). Create a folder named images inside the src directory and place all the images.

Our recipe categories section looks as below (we are going to develop this shortly):-

Recipe Categories (Image Courtesy: Google Images)

Each of the categories is represented with a Bootstrap Card. Let us create our Card component:-

Card.js

Card.css

We will now import all the images in Recipes.js and display Card components as below:-

Recipes.js

Recipes.css

We have done a lot. Let us browse to our recipes link as below:

http://localhost:3000/recipes

Recipes Category
Category hovering displays Category Text

Setting Up API to fetch Recipe data

To fetch Recipe information, we will be using Recipe data API provided by https://www.edamam.com. In order to access API data from edamam, we need to sign up and get access to the APP_ID and APP_KEY. Note that we can fire 5 requests/minute with the free account. I have already created the account and retrieve my APP_ID and APP_KEY. Browse to https://www.edamam.com and set up your login and note down the APP_ID and APP_KEY

Add the following variables in Recipes.js. Replace placeholders with your account-specific data.

const APP_ID = “<Your APP_ID>”;
const APP_KEY = “<Your APP_KEY>”;

Add the following onImageClick method. This is used to change the application state and load data from edamam

onImageClick method

Add following method. This loads the recipes data from edamam API.

Loading data from edamam API using JavaScrip Fetch API

The data returned by edamam can’t be used as it is. We need to format the data to pick up the relevant data and form our own recipe object.

Sample data returned by edamam:

API data returned by edamam

Our formatter:

Formatting API data

Following is the JSON data after formatting. We are picking up the variables highlighted.

Formatted data

Recipes.js

Our final recipes component:

Final Recipes.js

Testing Our Application

Recipes Page

http://localhost:3000/recipes

Recipe Categories
Data Loading from API
List of all Recipes under Soup category
Back button to browse to the previous section

Part 3: Add Authentication in our Application

Presently, our application is not secured and anyone can view all our recipes. Let us secure it with Auth0.

Setting Up Auth0

We will first set up an account in Auth0 and configure our client Id. Head over to Auth0 and signup using any of the options provided.

Auth0 Signup

Create the tenant domain

Create Tenant Domain
Tell more to Auth
Auth 0 Dashboard

Click on the CREATE APPLICATION button and define a new application using the Single Page Web Applications option:-

Click CREATE and Select React Application.

Select Domain as configured in Create Tenant Domain. It looks like <domain>.auth0.com. Also, scroll down and configure the Allowed Callback URLs to http://localhost:3000/callback. Scroll down and save changes.

Callback URLs

Adding Authentication in our RecipeMart.com

We will create an Authentication component and it will provide authentication service in our application. We need to install auth0-js.

npm install — save auth0-js (its double hyphen)

Installing auth0-js

Create Auth.js in src folder.

Auth.js

Let’s add the following authentication information:

auth0 = new auth0.WebAuth({
domain: “<Your domain>”, → domain.auth0.com
clientID: “<Your Client Id>”,
redirectUri: “http://localhost:3000/callback",
audience: “https://<Your Domain>/userinfo", → https://domain.auth0.com/userinfo
responseType: “token id_token”,
scope: “openid profile”
})

All of this information can be found in the auth0 application dashboard.

Auth.js

Let us now enable authentication. First, add the auth to App.js so that we can use it in any component we would like:-

App.js

We have created an Auth object and propagating to downstream components.

App.js

Main.js

Callback.js

Remember the callback URL we had added in the auth0 application configuration? Yes, its http://localhost:3000/callback. We also had created a /callback endpoint previously. Once the user is authenticated, auth0 invokes this callback URL. It’s on us, where we want to redirect our user.

What we are doing here is that once the callback URL is invoked, we are redirecting the call to handleAuthentication(). There we are validating whether the request possesses valid tokens. If so, we are redirecting it to /recipes endpoint. Otherwise, to the /loginFailed endpoint.

We now have to secure /recipes endpoint. We are verifying if the user is authenticated then only display recipes. Otherwise, redirect for login.

Lastly, we will edit Header component to display the logout button for logged in users.

Part 4: Validating Authentication in our Application

We are done with our application development. Let us now test our application authentication.

http://localhost:3000/

Home Page

http://localhost:3000/recipes

Access Denied as we are not logged in. Application is displaying appropriate message:-

Accessing about page (http://localhost:3000/about). This is a public page and is accessible to everyone.

Let us try logging in:-

Click on the recipes link and then Sign In button. It redirects us to the login page. Note that, our application name — this is what we have configured earlier in auth0 configuration.

I will use my Google account for authentication. Once provided the credentials, it asks a confirmation.

Click Ok and we are presented with the following recipe category page:-

Recipe Page

Click on the Pizza category and we receive the following screen. Note that the additional Logout button is added as we are authenticated.

All Pizzas

We also have the Back button to browse back to the previous page:

Back button to visit the previous page

Click logout and we will be successfully logged out from the application.

Part 5: Conclusion

We have successfully developed this application and add the authentication aspect in it. Complete source code can found on Github.

Full Stack Developer, Manning Author for Spring Boot In Practice book, Technical Writer, Course Creator at Udemy. Find more at https://musibs.github.io