When creating a web app, a basic requirement is to make a login system with the help of which users can authenticate themselves before getting access to preserved resources or views.
If you wish to create a Node app, there is an authentication middleware for Node called Passport.
Passport provides authentication mechanisms with the help of a few commands. It is created for a singular purpose that is to authenticate requests.
Here we will learn how Node JS authentication with Passport JS and Passport local mongoose.
Passport-Local Mongoose is a Mongoose plugin that simplifies username creation and password login with Passport.
This module auto-generates salt and hash fields, you don’t require to hash the password with this crypto module, the passport-local-mongoose does this for you.
How is Salting of Password Important?
Whenever a user simply hashes their password and if there are two users in the database that have the same password, they will end up having the same hash.
Now, if any one of these passwords gets hacked then the hacker can reach each account that uses the same password because users with identical passwords have the same hash fields.
Therefore, before hashing, we prepend a unique string, just something unique. So that the hash is entirely different for every salt.
Also, Read – 7 Key Video Optimization Tips to Rank in YouTube and Google Search
Steps to Perform Authentication with Passport JS and Passport Local Mongoose
Firstly, you need to generate an express app by installing all the needed modules.
> npm install passport passport-local mongoose passport-local-mongoose --save
1) You Need to Create a Directory Structure as Shown Below:
--model ----user.js --route ----user.js --app.js
2) Need to Create a Model/User.js File That Will Define the User Schema
// importing the modules var mongoose = require('mongoose'); var Schema = mongoose.Schema; var passportLocalMongoose = require('passport-local-mongoose'); var UserSchema = new Schema({ email: {type: String, required:true, unique:true}, username : {type: String, unique: true, required:true}, }); // plugin for passport-local-mongoose UserSchema.plugin(passportLocalMongoose); // exporting the userschema module.exports = mongoose.model("User", UserSchema);
Note: In this schema, we don’t add any field for passwords because passport-local-mongoose doesn’t need it. Also, we don’t need to add any methods to hash our password for authentication as passport-local-mongoose will do that for us.
3) Configuring Passport/Passport-Local in App.js:
Firstly in app.js, you have to initialize the passport
app.use(passport.initialize()); app.use(passport.session());
Now the passport maintains persistent login sessions. For persistent sessions to work in the passport, the authenticated user must remain serialized to the session and deserialized when any subsequent requests are made.
With passport-local-mongoose it remains like this:
passport.serializeUser(User.serializeUser()); passport.deserializeUser(User.deserializeUser());
If you are not using passport-local-mongoose with the passport then the serialized and deserialized code can be somewhat different.
Now we have to set the strategies for the passport. For passport local mongoose the code would be like:
const User = require('./models/user');
const LocalStrategy = require('passport-local').Strategy; passport.use(new LocalStrategy(User.authenticate()));
In case, you are using only the passport without a passport-local-mongoose then you will have to write some code to compare passwords and all. But using this passport-local-mongoose, only those 2 lines are enough.
4) Next Comes the Creation of the Route/User.js File:
For this, you need to import the user-schema first, along with other required modules.
// importing modules const express = require('express'); const router = express.Router(); // importing the User Schema const User = require('../model/user');
5) Next is the Registering Part:
For registering the code should be:
router.post('/login', function(req, res) { Users=new User({email: req.body.email, username : req.body.username}); User.register(Users, req.body.password, function(err, user) { if (err) { res.json({success:false, message:"Your account could not be saved. Error: ", err}) }else{ res.json({success: true, message: "Your account has been saved"}) } }); });
In the above code, rather than defining our password in New user, we use the password with the User.Register() i.e. a passport-local-mongoose function. Now just check your database for your saved user, it will be like here:
{ "_id" : ObjectId("5ca8b66535947f4c1e93c4f1"), "username" : "username you gave", "email" : "email you gave", "salt" : "4c8f6e009c4523b23553d9479e25254b266c3b7dd2dbc6d4aaace01851c9687c", "hash" : "337de0df58406b25499b18f54229b9dd595b70e998fd02c7866d06d2a6b25870d23650 cdda829974a46e3166e535f1aeb6bc7ef182565009b1dcf57a64205b5548f6974b77c2e3a3c6aec5360d 661efb5155e68ad0e593c0f5fab7d690c2257df4369e9d5ac7e2fc93b5b014260c6f8fbb01034b3f85ec f5055cac0fb01a4a2288af2ce2a6563ed9b47852727749c7fe031b6b7fbb726196dbdfeeb6766d5cba6a 055f66eeacce685daef8b6c1aed0108df511c92d49150efb6473ee71c5149dd06bfb4f73cb60f9815af0 55f9fcd3ffd6fb99dce21aab021aced72881d3720f6a0975bfece4922282bb748e0412955e0afa2fb8c9 1e02fde8d8ed822bb3a55f040237cf80de0b1534de6bbafcb53f882c6eb03de4b4aa307828974eb51261 9d6231eca6edbeec4eb1436f1e45c27b9c2bfceccf3a9b42840f40c65fe499091ba6ebeb764b5d815a43 d73a888fdb58f821fbe5f7d92e20ff8d7c98e8164b4f10d5528fddbcc7737fd21b12d571355cc605eb36 f11e086e9bf860f959d0e2104a1f825d286c99d3fc6f62505d1fde8601345c699ea08dcc071e5547835c 16957d3830998a10762ebd143dc557d6a96e4b88312e1e4c51622fef3939656c992508e47ddc148696df 3152af76286d636d4814a0dc608f72cd507c617feb77cbba36c5b017492df5f28a7a3f3b7881caf6fb4a21f5f266f8e38683deb05a6de43114", "__v" : 0 }
You will notice here that there is no field for the password, alternatively, passport-local-mongoose generated salt and hash for you, you are not required to set salt plus and fields in your schema.
Passport-local-mongoose will hold your username unique, i.e. if the username already exists it will return “UserExistsError”.
6) For Login:
Now for login,
userController.doLogin = function(req, res) { if(!req.body.username){ res.json({success: false, message: "Username was not given"}) } else { if(!req.body.password){ res.json({success: false, message: "Password was not given"}) }else{ passport.authenticate('local', function (err, user, info) { if(err){ res.json({success: false, message: err}) } else{ if (! user) { res.json({success: false, message: 'username or password incorrect'}) } else{ req.login(user, function(err){ if(err){ res.json({success: false, message: err}) }else{ const token = jwt.sign({userId : user._id, username:user.username}, secretkey, {expiresIn: '24h'}) res.json({success:true, message:"Authentication successful", token: token }); } }) } } })(req, res); } } };
Also, Read – How to Convert CSV to JSON File in Node.JS
7) Resetting or Changing Passwords:
Resetting or changing passwords requires 2 simple functions in passport-local-mongoose:
setPassword function and changePassword function
When a user forgets the password then the SetPassword is used
For setPassword code is:
user.setPassword(req.body.password, function(err, user){ ..
When the user wants to change the password then the ChangePassword is used.
For change password code is:
user.changePassword(req.body.oldpassword, req.body.newpassword, function(err) ...
Users can directly call them in their router files.
Conclusion:
Well, we’re finally at the end. In the above article, you will learn how to implement local authentication using Passport in a Node.js application along with resetting or changing the passwords.
We hope you liked this tutorial and perhaps got some inspiration for your next project. Happy coding!
Thanks fоr every other mɑgnificent post. Where
else couⅼd anybody get that type of information in such an ideal way of writing?
I’ve a рresentation subsequent week, and I’m on the search for such info.