Passport-Local Authentication
By: James Kaviyil Jose
Tags: Nodejs, Passportjs, Authentication, Servers, Expressjs

I would like to share how I configured Passport.js for my Node.js Express Server. I was looking for something to refer but couldn’t find any matching my requirements. I was working on a web-app that needed authentication that was not so complex but yet efficient.

Photo by Jason Strull on Unsplash

My requirements were:

Authenticate using email and password Separate routes for login and signup

Based on the requirements, I encountered Passport.js, which is an authentication middleware for Node.js. It’s simple way of implementation made me explore it.

Photo by Samuel Regan-Asante on Unsplash

Here’s the folder structure of my server:

server

|____config

|____passport-config.js

|____routes

|____auth.js //Containing the login and signup routes

|____models

|____user.js

|____node_modules

|____package-lock.json

|____package.json

|____index.js



Here’s how I configured my Node Express Server to authenticate using Passport.js:

index.js

const express = require('express'); const cors = require('cors'); const bodyParser = require('body-parser'); const mongoose = require('mongoose'); const morgan = require('morgan'); const keys = require('./config/keys'); const passport = require('passport'); require('./config/passport-config'); const port = process.env.PORT || 9000; //Configure server port const app = express(); //Initialize express app const MONGO_URI = keys.mongoDB.URI; //Use your MongoDB Connection URI app.use(morgan('combined')); //Outputs the requests to the server app.use(bodyParser.json()); app.use(cors()); app.use(passport.initialize()); //Initialize passportjs //Used to set the value of user upon authentication app.use(passport.session()); app.listen(port); console.log(`Listening On http://localhost:${port}`); mongoose .connect(MONGO_URI, { useNewUrlParser: true }) .then(console.log(`MongoDB connected`)) .catch(err => console.log(err)); app.use('/users', require('./routes/auth')); module.exports = app;

The user schema can be defined as:

models/User.js

const mongoose = require('mongoose'); const UserSchema = new mongoose.Schema({ username: { type: String,

required: true,

unique: true }, hash: String, salt: String }); module.exports = User = mongoose.model("users",UserSchema);

Now, let’s configure the local strategy for Passport.js authentication.

Passport.js can be used for various authentication mechanisms, these are known as strategies.

Here, I needed email-password authentication, so, I used passport-local strategy which authenticates using username and password.

We can modify the strategy to use email as usernameField, so that there are no confusions for authenticating.

config/passport-config.js

const passport = require('passport'); const LocalStrategy = require('passport-local').Strategy; const User = require('../models/user'); const crypto = require('crypto'); const customFields = { usernameField: 'username', passwordField: 'pw' }; const verifyCallback = (username, password, done) => { User.findOne({ username: username }) .then((user) => { if (!user) { return done(null, false) } var hashVerify = crypto.pbkdf2Sync(password, salt, 10000, 64, 'sha512').toString('hex'); const isValid = (hashVerify==user.hash)? true:false; if (isValid) { return done(null, user); } else { return done(null, false); } }) .catch((err) => { done(err); }); } const strategy = new LocalStrategy(customFields, verifyCallback); passport.use(strategy); passport.serializeUser((user, done) => { done(null, user.id); }); passport.deserializeUser((userId, done) => { User.findById(userId) .then((user) => { done(null, user); }) .catch(err => done(err)) });

Now, let’s define the routes in the auth.js file:

const router = require('express').Router(); const passport = require('passport'); const User = require('../models/user'); router.post('/login', passport.authenticate('local', { failureRedirect: '/login' }), (req, res) => { res.send({status: "Success", user: req.user.username}); }); router.post('/register', (req, res, next) => { var salt = crypto.randomBytes(32).toString('hex'); var genHash = crypto.pbkdf2Sync(password, salt, 10000, 64, 'sha512').toString('hex'); const salt = salt; const hash = genHash; const newUser = new User({ username: req.body.username, hash: hash, salt: salt }); newUser.save() .then((user) => { console.log(user); res.send({status: "Success", user: user}); }); }); module.exports = router;

By now, we have implemented passport.js for authenticating our users.

We can now test the API by running the index.js file using the command:

node index.js

Which will give the output:

Output

I used Postman for testing my API. Try sending requests to localhost:9000/users/register & localhost:9000/users/login and check whether the required response is obtained.

Congrats! Now you have completed the authentication part for your server. Thank you for taking time reading this article. Hope this was beneficial for you.