Basic User Authentication in Express

Aditya Naik
Nomads Of Code
Published in
5 min readJun 26, 2020

using passport local strategy (email + password)

Photo by iMattSmart on Unsplash

This is Part 4 of multi-part series on ExpressJS.

You can find Part 1 here. It talks about building a basic express api and setting up mocha for testing.

You can find Part 2 here. It talks about setting up PostgreSQL, sequelize for connecting express api with databases.

You can find Part 3 here. It talks about setting up associations (has many as well as belongs to) between two models.

You know the drill by now, to the tests!

Add a test for POST /login route

Let’s add a test to make sure users can find the login route and our api is able to find them and log them in.

touch test/auth.spec.js

We send user email and password to POST /login route and expect response code to be 200.

Simple enough.

Update factory

We need to update user factory and also the helper we have set up at the start of the test.

We add email and encryptedPassword fields to our user factory.

Update helper

We should update the way we create our user, because now using a specific email is important to us in our tests.

Before we move forward, clear the seeds.

Set up Clear seeds functionality

Update package.json scripts and add two scripts instead of seed command we had earlier:

“seed:create”: “node ./src/app.js create”, will create seeds

“seed:clean”: “node ./src/app.js clean”, will clean our database

Update our seeds file with clean seeds function

in deleteSeeds method, we destroy all instances of User and Post.

Finally, we hook it up in our app.js

We require the method from seeders and set up conditionals to execute create or destroy seeds functionality as expected.

run npm run seed:clean and check http:localhost:3000/posts by running npm run start and you should get an empty array.

This is good.

Time to code and get the tests to go green!

Setting up Passport and Passport-local

Install passport and passport-local

npm i passport passport-local

create auth folder and index.js to hold our login logic, use passport local strategy to resolve login logic.

To summarize the code —

  • We set up a POST /login route using router.
  • We call in passport.authenticate command, and inform passport that we want it to use local strategy.
  • We define local strategy by passport.use and create a new LocalStrategy , where we find a user that has email from our incoming request.
  • If we indeed have such a user, we confirm the encryptedPassword is valid by using validatePassword method we added to User model.
  • Once the authentication is confirmed, we return User object using the Done . Else we just send false .

The user object is now attached to request as req.user .

Of course, all the code above is for naught, if we don’t actually use it.

We update our app.js like thus —

Just import the file const auth = require(‘./auth’)

and use it like app.use(auth) .

Time to actually add email and encryptedPassword columns to our User model.

Add email and encrypted password as columns for user model

First step — generate a migration.

Next up — Update our migration file to add two columns to our User model.

Next — Run the migration by sequelize db:migrate to update our database table.

Before we update our User model with email and encryptedPassword columns, we shall set up a package which helps us to actually encrypt the incoming password.

Use bcryptjs to encrypt and save password —

npm install bcryptjs

Now we update our User model —

A few interesting things are happening here —

  • At the top, we added email and password field and also added some validations

email: { type: DataTypes.STRING, isEmail: true, unique: true, allowNull: false, }

encryptedPassword: { type: DataTypes.STRING, allowNull: false, }

  • Then we add a beforeCreate action, where we encrypt the incoming password. This is used when we create a new user
  • We also define validatePassword where bcrypt just does all the hard work of comparing our stored password ( which is encrypted) and the incoming password, and let’s us know if both the passwords match or not
  • Finally we have cryptPassword function, which actually handles encryption. It generates salt and hashes the plain-text password.

What we did till now

  • Create and use a POST /login route
  • Set up Passport local strategy and verify incoming email and password. Send appropriate response. After succesful authentication, req.user is available.
  • Update User model and create migration to update db tables.

This is everything we have to do in order for the tests to go green!

But wait!

Even though the login is successful, how will our API remember a user when he makes another network request?

That is a valid question, and has many solutions.

We will look at one of them, the Passport-JWT, in the next article.

Here is Part 5.

Craft Academy is a Tech Education Provider that aims to bring new talent to the market and help to solve the shortage of tech workers. We are founded on the belief that modern development standards, agile methodologies, and business skills are fundamental for IT professionals.

Our primary service is a 12-week coding bootcamp designed to provide individuals with a foundation of skills that allows them to enter the industry as junior developers.

With that foundation, our learners find employment in various industries or start their own businesses that bring new innovations to the market.

Would you like to know more about what we do? Follow us here on Medium, Facebook, Twitter or visit our website.

--

--