Security is one of the most important considerations when building a production app, and often times it is left out as a second thought in the client-heavy apps built using React, Angular, and what not in the JAM stack.

In this tutorial post, I’ll be going over how to achieve securing a web app by creating a TodoMVC app which only allows modification on the data via a Node/Express API (which we’re going to build). All the TodoMVC app data will be stored securely in an appbase.io app.

In a previous post in this series, I wrote about implementing a client-side authentication for your React app. That is great when your users are only reading data from a server. However, when users can also create, update or modify their data, we need a server-side authentication flow for securing those operations.

We will start with the popular TodoMVC app and implement a simple authorization flow:

All users have Read access to the todos. Only an authenticated user has write access for Creating, Updating and Deleting their todos. For simplicity, we’ll be considering all the authenticated users to have write access.

You can check out the final app preview here.

Image: Final app, click to go to the live demo

Before We Can Get Started

We will use the TodoMVC app built with appbase.io and ReactiveSearch as a baseline to build our authenticated TodoMVC app.

Every Appbase app allows different sets of credentials (read and write) for read and write access control.

Getting read and write credentials for your app from dashboard

In this post, we will ensure that client side app can only hold the read credentials for our appbase app and we’ll extract the logic for write operations (for creating and editing todos) to a Node/Express server. This will allow us to restrict the write access only to authenticated users and also keep the write credentials safe.

for our appbase app and we’ll extract the logic for write operations (for creating and editing todos) to a Node/Express server. This will allow us to restrict the write access only to authenticated users and also keep the safe. We’ll be using Auth0 to handle authentication. Each request from the React app to the server will include an access_token that will be verified on the server using Express middleware. You can read more about the concept of access tokens within an authentication flow in this post.

App Design

The Set Up

The first step before we get into building the app would be to sign up for appbase.io and auth0.com.

In order to store the todos on appbase.io we would need an app. The simplest way to do it is by cloning the configured example app from this link. Look out for the “Clone this app” button on the bottom left corner.

Now that you have setup the appbase.io app, we’ll create a new client in Auth0 for this 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.

Image: Getting the Domain and Client Id

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:8001/callback // our app will run on 8001 port

http://yourhosteddomain:PORT // add if you are hosting it live

Image: Adding Allowed Callback URLs

Next we’ll need to create a new API for the audience identifier (a unique string value used for configuring auth0 instance in the app) which we’ll use later to verify the access tokens.

Image: Getting the audience identifier

Building the App

The directory structure of the client will look like this:

Client

├── 404.html // contains redirect script for gh-pages

├── index.html // root index html

├── dist // contains bundle

├── package.json

├── webpack.config.js // webpack configs

└── app

├── auth.js // authentication service

├── Callback.js // used when auth0 redirects to callback URL

├── history.js // used by auth service and react-router

├── index.js // renders the final app and handles routes

├── style.scss // custom styles

├── todoApp.js // parent component for the todo app

├── todoList.js // renders the list of visible todos

├── todoButton.js // button component used in the footer

├── todoFooter.js // child component which renders footer

├── todoItem.js // child component which renders todo item

├── todoModel.js // logic for handling requests

├── todomvc.scss // todomvc core styles

└── utils.js // utility methods

The directory structure of the express server will look like this:

Server

├── index.js // handles routes and requests

└── package.json

Here are the final repositories so you can refer to them anytime:

(i) TodoMVC Auth Client

(ii) TodoMVC Auth Server

1. Getting the projects ready

We are starting with the TodoMVC code from this previous post and adding an authentication flow to it. I’ve created starter repositories with the needed webpack configs and the dependencies which you can clone or fork as per your needs. Lets start by cloning these repositories into your local environment:

(i) TodoMVC Auth Client starter project

(ii) TodoMVC Auth Server starter project

After you’ve cloned the projects you can switch into the client project directory and test it out:

npm install

npm start

This will start the TodoMVC app (which has the entire logic on client side). Now that everything is up and running, we can start writing the authentication flow code. 😉

2. TodoItem UI Changes

In the app preview you might have noticed that each todo item displays the user avatar along with the name on hover. All the user information will be fetched when the user authenticates via Auth0 and stored along with the todo data. Let’s add a few lines into app/todoItem.js render function to display the user information:

render () {

return (

<li className={classNames({

completed: this.props.todo.completed,

editing: this.state.editing

})}

>

.. // We are adding the authenticated user's avatar and name

{

!this.state.editing &&

<img src={this.props.todo.avatar} className="user-avatar" data-tip={this.props.todo.name} />

}

<ReactTooltip effect="solid" />

</li>

)

}

The final component should look like as follows:

Snippet: Updated TodoItem with user information

3. Adding Authentication Service

We’ll be setting up the authentication service on the client side next.

First 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 by adding a basename of our project directory which is todomvc-auth-client in our case. You may change this to your own project name.

Adding the history service

Next we’ll be adding the auth service:

Adding authentication service

Here’s how this service works:

auth0 is a new instance of the Auth0 client. The domain , clientID and audience will be specific to your auth0 client (which you have created earlier). You’ll also notice in scope we’re requesting profile information. We’ll use this information for the user avatars. The redirectUri is set to localhost in development and to the project domain otherwise (which is github pages for this project)

is a new instance of the Auth0 client. The , and will be specific to your auth0 client (which you have created earlier). You’ll also notice in we’re requesting information. We’ll use this information for the user avatars. The is set to in 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

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

method calls the method on the auth0 client. We’ll call this after successful authentication to read the information from the page URL Auth0 redirects to after authentication setSession stores the information about access_token , id_token , expires_at , name and avatar in local storage so we can use it later without going through the authentication process again

stores the information about , , , and 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

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

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 getAccessToken returns the access_token from local storage if it exists, otherwise it throws an error. We’ll be sending this access_token to the server later in order to verify the request.

3. Adding a Callback component

The Callback component will handle redirects from auth0. This component will show a loading message till the session is set up.

Adding a Callback component

4. Adding isAuthenticated(..) check for TodoApp component

We can add a login link to app/todoApp.js clicking on which would initiate the login process (in the app/auth.js service). We’ll also be adding a check in each method and only proceed if the user is authenticated. For this we’ll use the isAuthenticated method in app/auth.js service.

Adding authentication check in todoApp component

Here I’m using the read-only credentials for my app in the ReactiveBase component. You can use your app’s credentials here (from appbase.io dashboard). The read-only credentials work well since we’re only accessing the data on the client-side. All the data writes will be handled by the server.

5. Setting up client routes and handling authentication

We’ll be using react-router-dom from react-router to handle all our routes in app/index.js . The handleAuthentication method is called after Callback component is rendered and parses the URL hash from the page auth0 redirects to after authentication.

Setting up client routes and handling authentication

We’ve set the following routes:

/ route is the main route which renders the TodoApp parent component

route is the main route which renders the parent component /callback route renders the Callback component and runs the handleAuthentication function to parse the token information from Auth0’s redirect URL.

6. Moving write logic to the server

In this step, we’ll be moving the write-related logic from app/todoModel.js to our server. Until now, we were able to modify the data directly from client side with exposed admin level appbase credentials which is not secure because anyone having the access to your app can exploit these credentials and modify the data.

We’ll be using the read only credentials in our client app so users can view the data but not modify it. Only an authenticated user will be able to modify the data through the Node/Express server.

We’ll be using the server’s root URL (http://localhost:8000) in the starter app and setting up the routes to handle POST, PUT and DELETE requests.

Let’s start by removing the write related logic from app/todoModel.js and substituting it with fetch requests to the server. All our requests will include the access_token in the header using the getAccessToken method from app/auth.js service which we can later verify on the server. Our requests will be following a simple convention:

POST to create new todos

to create new todos PUT to update an existing todo

to update an existing todo DELETE to delete a todo

We can also substitute our appbase app credentials here to read-only since we will not be performing index, update or delete operations directly from the client.

Updating todoModel to request server for write operations

Our client side app is ready, let’s finish the flow by adding routes to our server:

Adding Routes to Server

We’ve added a checkJwt() method to verify the access token received in the request. We’re passing this method to the express middleware before handling the requests in our routes. This method verifies the access token and the request will only be completed if the token is found to be valid.

You can now fire up both the server and the client in your local environment or deploy on your favorite platforms.

7. Deployments

The example client app is deployed on github pages. The starter project includes all the necessary configurations and can be deployed easily by creating and pushing to a gh-pages branch.

The server can be deployed easily using now. The starter project includes a now-start in package.json which is used by now to start the project. If you haven’t installed now you can do so by running:

npm i -g now

After it’s installed you can switch into your server directory and run now .

Deploying todomvc-auth-server using now

After following through the instructions, you can use the URL provided by now in you client app. Your TodoMVC auth app is ready to roll! 🚀

tl;dr Summary

In this post, we built authentication flow for a realtime TodoMVC example app and added a node server which allows only authenticated users to modify the data. We used auth0 to handle authentication and appbase.io as our database for storing all todo items. You might find the following links useful:

Further readings

If you liked this article, you’ll also enjoy the following posts: