Skip to main content

Full-Stack Web Authentication - Part 1


Comments: counting...

In this segment we will set up a full stack project that we will be using for the rest of this series


Welcome! Web authentication is a big topic, but this series will focus mainly on a handful of strategies that I typically utilize most. We will start simple and add on to the demo project to improve performance and security throughout the series.

I’ve set up a GitHub repository that you can follow along with if you’d like, I’ll keep a separate branch for each segment in the series.

A Note on Security

Bear in mind that security is the art of making unwanted behavior more difficult in an effort to deter anyone from succeeding in said behavior. There is no single thing you can do to make something secure, instead a combination of techniques will make something reasonably secure while still being reasonably usable, because security and ease of use are somewhat mutually exclusive.

Adding to that challenge, security is a constant cat-and-mouse game; it’s always evolving.

The Stack

We will be using React for the front-end, Express for the back-end, Prisma for Object-Relational Mapping (ORM), and PostgreSQL for the database. We will implement Redis, an in-memory database, later on in the series.

To make this series easier to follow we will not be using TypeScript.


To make the most of this series, you will need the following:

  • NodeJS installed on your computer
  • Docker or Docker Desktop installed on your computer (we will use Docker for PostgreSQL and Redis)
  • Working knowledge of Docker, JavaScript, Express, React, and Prisma is not necessarily required, but would be an advantage

Project Setup

We need to bootstrap a full stack app before we can do much else, here is our basic structure.

  • Project Directory
    • api: Back-end code
      • .env: Environment variables
      • primsa: Our database schema and migrations will be here
      • src
        • routes: Express routes
        • constants.js: Constant values
        • server.js: Express server
    • web: Front-end code
      • public: Static files
      • src
        • components
        • hooks
        • setupProxy.js: Used by http-proxy-middleware to proxy the back-end port.


Let’s create the api directory and install our dependencies.

NPM Scripts

  • start: Run develop mode
  • build: Build production code
  • serve: Serve production code
  • clean: Remove production code
  • prisma:format: Format the schema file
  • prisma:generate: Generate JavaScript for your scheme (in node_modules)
  • prisma:migrate:dev: Match the database to your schema, create migration if needed
  • prisma:migrate:deploy: Run migrations on the database


We’ll need some environment variables so we can easily deploy later. The optional values here will have defaults in the code.

We also need to tell Babel what to support, we’ll just use the defaults for now.


We’ll start with a basic schema for User, Role, Password, and Session.



We’ll set up a health check route for now just to make sure the API is working correctly.

It may seem silly to make an index file to export a single module, but I use this structure to keep everything easy to find and parse when you have complicated routes, you’ll see what I mean later in the series.

Now we need to set up our top-level router.

Express Server

The last thing we need to do for the API is tie it all together with Express.


We need an instance of PostgreSQL, if you don’t have one already we can spin one up with Docker.

Next, we need to generate the JavaScript for our schema.

The --prefix flag on npm will change the directory the command is run from, in this case the command will run in the api directory inside the current working directory.

Then we’ll provision the database with our schema, you will be asked to give the migration a name when you run this command, init is a good choice for this one, later on you’ll name your migrations based on what they are changing.

With that done, you can now run npm --prefix ./api start, and visit http://localhost:3001/healthcheck, you should see the JSON response { "success": true }.


Let’s create the web directory and install our dependencies.

Proxy the API

We want to make the API available at http://localhost:3000/api when we are in develop mode, to make development easy. The http-proxy-middleware package will find this file on its own and set up the proxy for us.

Front-End Environment

We don’t need dotenv on the front-end, instead we just need to preface our variable names with REACT_APP_.

Custom Hook for API Calls

To keep things tidy, we’ll put all of our API calls in a custom hook. If that gets unwieldy later we can move some of the logic to other files in a lib folder.

API Status Component

Let’s make a quick component to show the status of the API.

Now a quick adjustment to App.js and App.css to display the component.

Other Niceties

Since this is a mono-repo, let’s add a script to the root directory that starts both the front-end and back-end at the same time.

Now you should be able to run npm start from the root project directory, when you visit http://localhost:3000 you should see something like this.

Screenshot of running app

Lastly, check the GitHub repo for my ESLint and Prettier configurations if you are so inclined, they were omitted here because they are beyond the scope of this article.


We now have a very simple full-stack application set up with a React front-end that can communicate with our Express API, as well as a database and schema, which we will put to use in the next segment.

In the next segment, we will set up authentication routes on the API, make sure you so you don’t miss it!