DEV Community 👩‍💻👨‍💻

Cover image for Build a Passwordless Authentication in Node.js on Redis
Michael Owolabi
Michael Owolabi

Posted on

Build a Passwordless Authentication in Node.js on Redis

One of the most important and universal aspects of Software Development is how access to various services in the application is granted, over the years, many authentication models have been developed with various pros and cons. There is really no single perfect auth system without any flaws. It is impossible to have a system that is both “very” secure and convenient to use at the same time. The more we tend towards the side of “security”, the more difficult the user experience for most users, and various models have been developed to find that balance.
What is more practicable is to find what is more important in various use cases and apply it accordingly.

Like various other security systems have their origin traced back to the Roman empire, so can passwords be traced to the same root according to this Wikipedia page

Password has evolved a lot since its introduction and many encryption models have been developed over the years just to curb various password attacks. Sometimes, it’s not even that the password encryption model isn’t secure enough, in fact, most password breach is caused by human errors ranging from companies storing passwords in plain text, to users using weak passwords or just being careless or too trusting with their passwords.

Truth is that, as long as password exists, all these will continue to be an issue.

The most secure password is no password at all because, “If it exists, it can be cracked”.

What if we can eradicate passwords completely and be done with all the associated issues?

Image description

In this article, we are going to develop a password-less authentication system built on Redis where all the problems discussed above can be a thing of the past.

Please note that I’m not saying that this will be the most secure system, but at least we can be sure that our system will still be secured without all the associated problems listed above.

Why Redis for such an application you asked? For the simple reason that traditional databases are slow and Redis is super fast. We wouldn’t want our users to wait too long before they will be able to access our system now that the password is out of the way, would we? So let’s get to it.

Prerequisites

To be able to follow along with this tutorial, you need to have the following installed on your computer:
Node.js
npm
Code Editor (VSCode)
Postman/Web Browser
Mailgun Account

RedisInsight - Get one installed on your computer here if you don’t already have one.

Finally, you’ll need to have a Redis Enterprise account for your Redis cloud database. If you don’t already have that just head on to their website to create a free account.

Getting started

First, we are going to install the dependencies needed for this application so open your terminal and execute the following commands

cd desktop && mkdir passwordless-authentication && cd passwordless-authentication
Enter fullscreen mode Exit fullscreen mode

Initialize the directory to create a package.json file by running

npm init -y
Enter fullscreen mode Exit fullscreen mode

Install dependencies

Let’s install the various packages that we’ll be using for the development of this application by running the command below:

npm i express dotenv redis-om jsonwebtoken nodemailer
Enter fullscreen mode Exit fullscreen mode

Lastly, let’s install nodemon as a dev dependency to aid our development flow by running the command below:

npm i -D nodemon
Enter fullscreen mode Exit fullscreen mode

Now let’s create a simple Node.js server using express so as to be sure that everything is properly set up. To do this, create a new directory at the root of your project named “src” and inside it create a new file called index.js and paste the code below into the file.

In the scripts section of your package.json file setup the start scripts for your server by adding the following keys and values

"start": "nodemon index.js"
Enter fullscreen mode Exit fullscreen mode

Now start the server by running npm start` in the terminal. You should see something close to the screenshot below logged to your terminal.

Image description

Now that we are sure that our server is properly set up, the next thing we need to do is set up our Redis database to handle the storage of our events data.

Redis Enterprise Setup

To setup your Redis database, login to your Redis enterprise account here. If you haven’t created an account yet just head on to the Redis website and create a free account. You should use the free credit coupon on the signup page to explore Redis beyond the free tier offerings.

On your Redis enterprise dashboard click the “New subscription” button, select “Fixed plans” and then choose the 100MB storage space option. You can choose any cloud provider of your choice but for the sake of this tutorial, let’s use the default (AWS) then make sure your settings are a replica of the screenshot below.

Image description

Do not worry, you will not get charged for the plan you chose since you applied a $200 coupon so you can safely add your card. We needed this plan to activate data persistence for our Redis DB because it will be odd to have an event management platform where every time you come back to it, it’s always empty 😀.

But just if you’re still skeptical you can choose the free (30MB) option only that your data will not be persisted but you would still be able to follow along with this tutorial using that option.

Image description

Now on your subscription dashboard, click on the “New Database button”. Give your database a name and choose the Redis option under the “Type section” to specifically select the Redis module of choice which in our case is RediSearch and RedisJSON.

Make sure you also select the data persistence option of choice but in this case, we’ll be using the snapshot option that runs every hour. Click the “Activate database” button when you’re done to provision your database. After that, you should see the database configuration screen similar to the one below.

Image description

Visualizing your data

Now that we have set up our database properly, we need something to visualize our data stored in the Redis DB and this is where RedisInsight comes in. Now launch your RedisInsight and click the “Add Redis Database” button then copy and paste in your Redis enterprise DB connection string.

Image description

It is called “public endpoint” on your Redis enterprise DB configuration page. Then on the same DB configuration page, you would see your default username and password, copy those and paste them into your RedisInsght connection dialog after which you click the “Add Redis Database” button to connect to your Redis enterprise DB. You should see the DB summary on the next page which will be empty since there’s currently no data in your Redis database.

Image description

Connecting your Redis DB from the App

The next thing to do is to set up a connection to our Redis database from within the event manager app. To do this, create a new directory inside "src" called db and create a new file named "index.js" in the newly created db directory. Copy and paste the following code into the file.

{% embed https://gist.github.com/iMichaelOwolabi/ab7e7144aa3ea5e6033e7cdd22a2ee70 %}

Building the Passwordless Authentication

Now that all the building blocks have been set, let’s dive into building our authentication system without passwords.

The first thing we are going to do is to model our entity for authentication purpose. We will allow users to be able to log in with either their email or username so to do this, let’s create a directory in the src directory and name it repository. Inside the newly created repository, create a file called user.js and paste into it the code below.

{% embed https://gist.github.com/iMichaelOwolabi/c7dbc25e6706236e00c958edf0699068 %}

Here, we have modeled our authentication data and assigned the individual fields with the proper data type which is mostly string. You will notice that in the date fields, we have a new attribute “sortable”, this is something similar to “ORDER BY” in SQL which allows us to order the result of our query. In this case, we could fetch all users and order them from the most recently created to the least recent users.

We create an index on our user model by calling the "createIndex()" method on the repository from our schema. This secondary index is where the power of RediSearch shines the most. The performance of our search is directly proportional to how good our index is.

We’ll create a new directory in the src folder and name it routes. Inside the routes directory let’s create a new file called "authRouter.js" and paste in the following code:

{% embed https://gist.github.com/iMichaelOwolabi/0494dfab097b457855915367595b54d0 %}

This router file is where all our endpoints for the app is defined and it’s responsible for routing requests to the right controller function for execution.

You’ll notice that we imported some controller functions and a middleware into the authRouter file, so let’s go ahead and build them out. These auth methods here aren’t anything new that we haven’t seen before, the only difference is that instead of interfacing with traditional relational or Doc DB that directly write and read from the disk, we are using the super fast Redis as our DB which in turn makes our user authentication process fast.

So, create a new folder named controllers inside the src directory. In the newly created directory, create a new file named "authController.js" and paste the following code into it.

{% embed https://gist.github.com/iMichaelOwolabi/06cd1053d7e653ba920f0da725ac6e07 %}

In the code above, you could see some SQL-like query structure which makes the entire thing very friendly, this is made possible by Redis-om which is a new Redis client from Redis

Now, let’s sort out the dependent modules that we used in the auth controller file.

Even though our aim is to eliminate password from our authentication process in this app, we still need to make it secure else, we run the risk of allowing the entire Internet access to resource that shouldn’t be in the public view. So let’s create a new directory called utils straight inside the src directory. In the utils folder, create two new files namely, "jwtHelper.js" and "emailTransporter.js".

In the jwtHelper file copy and paste the following piece of code into it.

{% embed https://gist.github.com/iMichaelOwolabi/94d5a7282fe813b5bcffe970a35b93bc %}

Our approach to authenticate user simply involves sending the login credentials to the user’s email which serves as a means verification that even though the user isn’t using password to access their protected contents, we can still be sure they’re the ones requesting access that way which makes the system secure still.

Setting up email service

To send email, we need to user an email service provider and for the sake of this article, we are going to use Mailgun. To be able to send free emails, we need to add verified recipient so log in to your Mailgun account and click “sending” from the sidebar, from the list of dropdown options click “Domains”.

Image description

You should see the default domain provided you by Mailgun. Now click on the domain and you should see where you can add list of emails for verification.

Image description

Add the email you will be sending messages to for test purpose and verify the mail by accepting the terms from the email sent to the added email account. Something similar to what we have below.

Now that we’ve setup our email service, let’s plug it to the app so copy and paste the following code into the "emailTransporter" file.

{% embed https://gist.github.com/iMichaelOwolabi/4da4997767773f314914dbdefbd5c4db %}

We are getting closer to the end of the application. Let’s protect some of our endpoints from being accessible to unauthorized users. Create a new folder in the src directory named “middleware” then create a new file in the new folder called "index.js" and paste the code below into the file.

{% embed https://gist.github.com/iMichaelOwolabi/5aa9ac993e3104aa7673143c135111c0 %}

Bringing it altogether

Now that we’re done building the individual parts of the application, we need to find a way to make sure our server is aware of our routes so we are going to plug our auth router to the server by importing it to the index.js file at the root of the project. Just copy the following code and replace the content of the index.js file with it.

Lastly create a new file at the root of your project named ".env"
The env file is what we are going to use to store the secret values used in the app so that they’re not exposed to the public. In the env file, copy and paste the following then populate the values accordingly.

`
PORT=
REDIS_DB_URL=
REDIS_DB_USER=
REDIS_DB_PASS=
TOKENEXPIRATIONTIME=
JWTSECRET=

MAILGUN_SMTP_HOSTNAME=
SMTP_PORT=
MAILGUN_SMTP_USERNAME=
MAILGUN_SMTP_PASSWORD=
`

We have successfully built a passwordless authentication system in Node.js powered by Redis.

Startup your server by running the following command from your terminal right from the project directory

npm start

Now let’s test our implementations so far. Open Postman and create a user account, login and verify.

Creating a user account

Image description

Image description

Login screenshot

Image description

Image description

Congratulations on making it this far. Do share your thoughts in the comment section.

The complete code can be found in this Github Repository.

This post is in collaboration with Redis.

If you enjoyed working with us like we enjoyed working with you and want to continue writing for us, we’re now accepting applications for more blogs. You can apply here

Top comments (1)

Collapse
 
spock123 profile image
Lars Rye Jeppesen

Great article.
I'd wager you could just have spun up a Redis container, but I get it.

Visualizing Promises and Async/Await 🤯

async await

☝️ Check out this all-time classic DEV post