Using Passport for authentication in Node.js - LogRocket Blog (2024)

Implementing application authentication from scratch can be a huge headache for developers. And, if it’s not implemented correctly, the authentication process can lead to vulnerabilities within a system.

Using Passport for authentication in Node.js - LogRocket Blog (1)

In this article, we will implement authentication in a Node.js application using the Passport library and MongoDB.

What is Passport.js?

Passport is a popular, modular authentication middleware for Node.js applications. With it, authentication can be easily integrated into any Node- and Express-based app. The Passport library provides more than 500 authentication mechanisms, including OAuth, JWT, and simple username and password based authentication.

Using Passport makes it easy to integrate more than one type of authentication into the application, too. We are going to use the mongoose-local strategy in this article to implement the authentication.

Creating the folder structure of the Node app

First, let’s create specific folders for our files, like so:

Using Passport for authentication in Node.js - LogRocket Blog (2)

Here, the routes folder contains the file for all the routes. The views folder contains the ejs files that will be displayed, and the layout folder contains the ejs layout code.

Other than that, we have a .env file to store keys, an index.js file as an app starting point, and a userDetails.js file for Mongoose schema.

Building an authentication system with Passport, passport-local-mongoose, and MongoDB is extremely simple, but before moving forward to building the application, we will need a MongoDB cluster.

You can use your self-hosted version of MongoDB, or you can use MongoDB Atlas. In either case, create a MongoDB database first and store the SRV URI in the .env file.

Initializing Node and installing the packages

Once we are done creating a database, let’s initialize the folder with npm. Create a new folder and initialize it with npm init -y.

Next, install the dependencies. Here is a list of them:

  • express: we will use the Express framework for our web application
  • mongoose: the MongoDB driver for Node.js will be used to connect with MongoDB
  • ejs: our templating engine
  • express-ejs-layouts: this will be used for layouts
  • dotenv: this package loads the environment variables from a file called .env to process.env
  • connect-ensure-login: this protects the pages that require authentication
  • passport and passport-local-mongoose: for implementing authentication
  • express-session: to create and manage the sessions

Install this package with:

npm i express mongoose ejs express-ejs-layouts dotenv connect-ensure-login passport passport-local-mongoose express-session

We will use the nodemon dev dependency. Install the dev dependency using npm i -D nodemon, then change the scripts section of the package.json file with these two lines:

"scripts": { "start": "node index.js", "dev": "nodemon index.js" }

Creating views and layouts

Because we are going to use ejs as the templating engine, we are using the express-ejs-layouts package to build our default layout.

Although installing this plugin is optional, it’s handy when working with a large project. First, create a folder called views in the root directory, then create a folder called layout inside the views directory.

Over 200k developers use LogRocket to create better digital experiencesLearn more →

Create a file called main.ejs inside the layout directory. I am using Bootstrap CSS to style the web pages in this application, so I won’t need to write any CSS. I am not going to explain the HTML files here, as they are pretty straightforward and can be understood easily. Here is the code for the main.ejs file:

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link href="https://cdn.jsdelivr.net/npm/[emailprotected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"> <script src="https://cdn.jsdelivr.net/npm/[emailprotected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script> <title> <%- title %> </title></head><body> <%- body %></body></html>

In the header section, we have imported Bootstrap CSS and JavaScript using CDN. The text inside the title tag and the body will be changed for each view.

Because of this, we are using <%- title %> and <%- body %> literals. We will pass the title from our routes file, and the body will render the HTML body.

This is all that is needed to add to the main.ejs file. Let me show you the code for the other three pages.

1. index.ejs

<div class="px-4 py-5 my-5 text-center"> <img class="d-block mx-auto mb-4" src="https://uilogos.co/img/logomark/u-mark.png" alt="" width="auto" height="150"> <h1 class="display-5 fw-bold">Your Login Page</h1> <div class="col-lg-6 mx-auto"> <p class="lead mb-4">Lorem ipsum dolor sit amet consectetur, adipisicing elit. Quod, quidem. Distinctio, natus, recusandae nostrum beatae provident aut quasi sequi eos nemo et quia dolor ipsum reprehenderit molestiae id facere sunt.</p> <div class="d-grid gap-2 d-sm-flex justify-content-sm-center"> <a type="button" class="btn btn-primary btn-lg px-4 gap-3 me-2" href="/login">Log In</a> </div> </div></div>

Here’s what it will look like when we render it:

Using Passport for authentication in Node.js - LogRocket Blog (5)

2. login.ejs

<div class="px-4 py-5 my-5 text-center"> <img class="d-block mx-auto mb-4" src="https://uilogos.co/img/logomark/u-mark.png" alt="" width="auto" height="150"> <h1 class="display-5 fw-bold">Login Here</h1> <div class="col-lg-3 mx-auto"> <form action="/login" method="POST"> <div class="mb-2"> <label for="username" class="form-label">Username</label> <input type="text" class="form-control" name="username" placeholder="Username" required> </div> <div class="mb-2"> <label for="password" class="form-label">Password</label> <input type="password" class="form-control" name="password" placeholder="Password" required> </div> <button type="submit" class="btn btn-primary mt-2">Submit</button> </form> </div></div>

The only thing to notice here is that we are hitting the login route using the POST method in the form action. Other than that, it is a simple HTML form with labels. The login page will look like this:

Using Passport for authentication in Node.js - LogRocket Blog (6)

3. secret.ejs

<div class="px-4 py-5 my-5 text-center"> <img class="d-block mx-auto mb-4" src="https://uilogos.co/img/logomark/u-mark.png" alt="" width="auto" height="150"> <h1 class="display-5 fw-bold">Welcome to the Secret Page</h1> <div class="col-lg-6 mx-auto"> <p class="lead mb-4">You've Successfully Entered the Secret Page</p> </div> <div class="d-grid gap-2 d-sm-flex justify-content-sm-center"> <a href="/logout" type="button" class="btn btn-danger btn-lg px-4 gap-3">Log Out</a> </div></div>

The secret page will look like this:

Using Passport for authentication in Node.js - LogRocket Blog (7)

This page contains a button called logout that will log out the users.
However, none of these pages will render yet because we haven’t set up our server. Let’s do that now.

Setting up the server

Let’s import the packages in the index.js file.

// Requiring Modulesconst express = require('express');var expressLayouts = require('express-ejs-layouts');const app = express();// set up view engine and layoutapp.use(expressLayouts);app.set('layout', './layout/main');app.set('view engine', 'ejs');app.use(express.urlencoded({ extended: false }));const PORT = process.env.PORT || 3000;// Set up express serverconst server = app.listen(PORT, () => { console.log(`Listening on port ${PORT}`);});

Here, we import the express and the express-ejs-layouts package. After that, we initialize express and express-ejs-layouts with const app = express() and app.use(expressLayouts).

The app.set('layout', './layout/main') is setting up the main file as the layout, and app.set('view engine', 'ejs') is setting ejs as the templating engine. app.use(express.urlencoded({ extended: false })) works as the body parser. And finally, we are creating our server on port 3000.

Now, let’s create a new folder called routes, and inside the folder, create a new file called router.js.

More great articles from LogRocket:

  • Don't miss a moment with The Replay, a curated newsletter from LogRocket
  • Learn how LogRocket's Galileo cuts through the noise to proactively resolve issues in your app
  • Use React's useEffect to optimize your application's performance
  • Switch between multiple versions of Node
  • Discover how to use the React children prop with TypeScript
  • Explore creating a custom mouse cursor with CSS
  • Advisory boards aren’t just for executives. Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
const express = require('express');const router = express.Router();const connectEnsureLogin = require('connect-ensure-login');const passport = require('passport');// GET Routesrouter.get('/', (req, res) => { res.render('index', { title: 'Home' });});router.get('/login', (req, res) => { res.render('login', { title: 'Login' });});router.get('/secret', connectEnsureLogin.ensureLoggedIn(), (req, res) => res.render('secret', { title: 'Secret Page' }));router.get('/logout', (req, res) => { req.logout(); res.redirect('/');});// POST Routesrouter.post( '/login', passport.authenticate('local', { failureRedirect: '/login', successRedirect: '/secret', }), (req, res) => { console.log(req.user); });module.exports = router;

As you can see from the above code, we have three GET routes and one POST route. First, we have added the necessary packages.

The connectEnsureLogin.ensureLoggedIn() middleware in the secret route ensures that the user is prohibited from entering the page without logging in.

Inside the POST route, the passport.authenticate middleware authenticates the user with local strategy, and, if the user succeeds in logging in, it’ll redirect to the secret route. Otherwise, it’ll redirect to the login route.

We are also passing the title of the pages through the title variable. The req.logout() is a passport method that logs out the user. Finally, we are exporting the router.

Setting up user schema with MongoDB

Create a new file in the root directory named userDetails.js.

const mongoose = require('mongoose');const passportLocalMongoose = require('passport-local-mongoose');require('dotenv').config();// Connecting Mongoosemongoose.connect(process.env.MONGODB_URI, { useNewUrlParser: true, useUnifiedTopology: true,});// Setting up the schemaconst User = new mongoose.Schema({ username: String, password: String,});// Setting up the passport pluginUser.plugin(passportLocalMongoose);module.exports = mongoose.model('User', User);

We require mongoose to connect with MongoDB, and passport-local-mongoose makes it extremely easy to integrate username and password authentication with MongoDB.

We set up the dotenv package to use the environment variables in the next line.

Then, we’re connecting to the database using mongoose. The User variable is holding the mongoose schema. The User.plugin(passportLocalMongoose) method generates and stores the hash, salt, and username in the database for every user. Finally, we export the schema.

We are almost done. We just need to set up our index.js file.

Initializing Passport in the Node app

Let’s import the Passport and express-session modules, router.js, and the userDetails.js file. Then, set up the session using the express-session package:

const passport = require('passport');const session = require('express-session');const UserDetails = require('./userDetails');const routes = require('./routes/router');require('dotenv').config();// Set up sessionapp.use( session({ secret: process.env.SECRET, resave: false, saveUninitialized: true, }));

The secret is stored in the .env file, and it signs the session ID cookie. If the resave flag is set to true, the session data will be forcibly stored. We don’t want this because the saveUninitialized will forcibly save uninitialized sessions when set to true. You can read in detail about the package here.

Now, set up Passport by adding the following lines:

// Set up Passportapp.use(passport.initialize());app.use(passport.session());

We are initializing Passport and the session authentication middleware first. Once this is done, we have to set up the local authentication.

passport.use(UserDetails.createStrategy());passport.serializeUser(UserDetails.serializeUser());passport.deserializeUser(UserDetails.deserializeUser());

The above code adds local authentication to our Node app. First, we are setting the local strategy on the UserDetails model by calling the createStrategy method.

Then, the serializeUser method serializes the passed user instance on authentication, and the deserializeUser instance is called on every subsequent request to de-serialize the user.

Now add this code in your index file and run index.js only once:

UserDetails.register({username:'nemo', active: false}, '123');

The above line will register a user with username nemo with password 123. If you check your MongoDB database now, you’ll see the user.

The final index.js file will look like this:

// Requiring Modulesconst express = require('express');var expressLayouts = require('express-ejs-layouts');const app = express();const passport = require('passport');const session = require('express-session');const UserDetails = require('./userDetails');const routes = require('./routes/router');require('dotenv').config();// Set up view engine and layoutapp.use(expressLayouts);app.set('layout', './layout/main');app.set('view engine', 'ejs');// Set up sessionapp.use( session({ secret: process.env.SECRET, resave: false, saveUninitialized: true, }));app.use(express.urlencoded({ extended: false }));// Set up Passportapp.use(passport.initialize());app.use(passport.session());passport.use(UserDetails.createStrategy());passport.serializeUser(UserDetails.serializeUser());passport.deserializeUser(UserDetails.deserializeUser());app.use(routes);// Set up Express serverconst server = app.listen(3000, () => { console.log(`Listening on port ${server.address().port}`);});UserDetails.register({ username: 'nemo', active: false }, '123');

This completes the authentication. Check the below GIF to see it in action.

Using Passport for authentication in Node.js - LogRocket Blog (8)

Conclusion

Authentication is an important and integral part of many web applications. This article covered how to integrate authentication to a Node.js application using the Passport library and MongoDB.

You can also check out the Passport Docs for more authentication strategies to implement in your application. I hope you enjoyed the read. The complete code can be found in this GitHub repo.

200s only Using Passport for authentication in Node.js - LogRocket Blog (9) Monitor failed and slow network requests in production

Deploying a Node-based web app or website is the easy part. Making sure your Node instance continues to serve resources to your app is where things get tougher. If you’re interested in ensuring requests to the backend or third-party services are successful, try LogRocket.

LogRocket is like a DVR for web and mobile apps, recording literally everything that happens while a user interacts with your app. Instead of guessing why problems happen, you can aggregate and report on problematic network requests to quickly understand the root cause.

LogRocket instruments your app to record baseline performance timings such as page load time, time to first byte, slow network requests, and also logs Redux, NgRx, and Vuex actions/state. Start monitoring for free.

Using Passport for authentication in Node.js - LogRocket Blog (2024)

FAQs

Is Passport.js good for authentication? ›

Passport is authentication middleware for Node.js. Extremely flexible and modular, Passport can be unobtrusively dropped in to any Express-based web application. A comprehensive set of strategies support authentication using a username and password, Facebook, Twitter, and more.

What are the alternatives to Passport authentication? ›

Alternatively, view Passport alternatives based on common mentions on social networks and blogs.
  • everyauth. 7.0 0.0 L5 Passport VS everyauth. ...
  • Grant. 7.0 5.7 L5 Passport VS Grant. ...
  • passwordless. 5.9 0.0 L4 Passport VS passwordless. ...
  • Lockit. 4.1 0.0 L5 Passport VS Lockit. ...
  • CloudRail. 3.5 0.0 L5 Passport VS CloudRail.
Jun 1, 2024

What does a Passport use do? ›

Passport's sole purpose is to authenticate requests, which it does through an extensible set of plugins known as strategies. Passport does not mount routes or assume any particular database schema, which maximizes flexibility and allows application-level decisions to be made by the developer.

What does Passport local strategy do? ›

The local authentication strategy authenticates users using a username and password. The strategy requires a verify callback, which accepts these credentials and calls done providing a user.

Which is better, JWT or passport? ›

JWT is a standardized token-based authentication mechanism that is widely supported and used for transmitting authentication information. Passport, on the other hand, is a flexible and extensible middleware that provides a strategy-based authentication framework for Node.

Which authentication method is more reliable? ›

More Secure: Biometrics. Biometric authentication methods rely on something you are. That makes them hard to steal, difficult to misplace or share, and impossible to forget.

When should I use my passport? ›

U.S. Passport: U.S. citizens may present a valid U.S. passport when traveling via air between the United States and Canada, Mexico, Central and South America, the Caribbean, and Bermuda, and may also use a U.S. passport when traveling via sea and land borders (including ferry crossings).

What is so special about passport? ›

In addition to facilitating travel, passports are a key mechanism for border security and regulating migration; they may also serve as official identification for various domestic purposes.

Why use a passport? ›

A passport is used to verify one's country of citizenship. If traveling outside your country, it is used to regain entry into your country of citizenship. Passports include your photo, name, birth date, gender and physical characteristics. For U.S. citizens, some countries only require a passport for re-entry.

What is the best API for authentication? ›

Best API authentication protocols
  1. OAuth (Open Authorization) OAuth is an industry-standard authentication protocol that allows secure access to resources on behalf of a user or application. ...
  2. Bearer tokens. Bearer tokens are a simple way to authenticate API requests. ...
  3. API keys. ...
  4. JSON Web Tokens (JWT) ...
  5. Basic authentication.
Oct 25, 2023

What is the best authentication method in node JS? ›

2FA/MFA: The highest level of authentication in Node is known as 2FA/MFA or two-factor authentication/multi-factor authentication. Authenticating the user requires additional PIN or security questions. One-time password: Access to numerous applications can be made possible by using single sign-on or SSO.

What is the best authentication type? ›

1. Biometric Authentication Methods. Biometric authentication relies on the unique biological traits of a user in order to verify their identity. This makes biometrics one of the most secure authentication methods as of today.

What is the difference between Bcrypt and passport js? ›

Passport is a library to help you implement authorisation in a NodeJS app. The node bcrypt library provides a function to hash a string (which will be a password), it doesn't have any scope beyond that.

Top Articles
How To Make Money as a Stay-at-Home Mom or Dad (2024) - Shopify
Nobody Wants to Be the Noisy Neighbor: Tips for Keeping Your Sound Down
Fernald Gun And Knife Show
Dairy Queen Lobby Hours
Fat Hog Prices Today
Libiyi Sawsharpener
Busted Newspaper Zapata Tx
Jailbase Orlando
East Cocalico Police Department
Find All Subdomains
Doublelist Paducah Ky
Konkurrenz für Kioske: 7-Eleven will Minisupermärkte in Deutschland etablieren
Heska Ulite
Nichole Monskey
Love Compatibility Test / Calculator by Horoscope | MyAstrology
Bros Movie Wiki
Restaurants Near Paramount Theater Cedar Rapids
Bx11
Mzinchaleft
Boston Gang Map
Jellyfin Ps5
Sni 35 Wiring Diagram
Weepinbell Gen 3 Learnset
Glenda Mitchell Law Firm: Law Firm Profile
Tyrone Unblocked Games Bitlife
Universal Stone Llc - Slab Warehouse & Fabrication
Japanese Mushrooms: 10 Popular Varieties and Simple Recipes - Japan Travel Guide MATCHA
8005607994
Boston Dynamics’ new humanoid moves like no robot you’ve ever seen
Lexus Credit Card Login
Tokyo Spa Memphis Reviews
Effingham Daily News Police Report
Chelsea Hardie Leaked
10 Best Quotes From Venom (2018)
Lincoln Financial Field, section 110, row 4, home of Philadelphia Eagles, Temple Owls, page 1
Www.craigslist.com Syracuse Ny
Litter-Robot 3 Pinch Contact & DFI Kit
Crystal Mcbooty
Synchrony Manage Account
Marcus Roberts 1040 Answers
Directions To Cvs Pharmacy
Dwc Qme Database
The Wait Odotus 2021 Watch Online Free
Ehome America Coupon Code
Child care centers take steps to avoid COVID-19 shutdowns; some require masks for kids
John Wick: Kapitel 4 (2023)
25 Hotels TRULY CLOSEST to Woollett Aquatics Center, Irvine, CA
New Starfield Deep-Dive Reveals How Shattered Space DLC Will Finally Fix The Game's Biggest Combat Flaw
4Chan Zelda Totk
Greg Steube Height
Congressional hopeful Aisha Mills sees district as an economical model
Tyrone Dave Chappelle Show Gif
Latest Posts
Article information

Author: Twana Towne Ret

Last Updated:

Views: 5446

Rating: 4.3 / 5 (64 voted)

Reviews: 95% of readers found this page helpful

Author information

Name: Twana Towne Ret

Birthday: 1994-03-19

Address: Apt. 990 97439 Corwin Motorway, Port Eliseoburgh, NM 99144-2618

Phone: +5958753152963

Job: National Specialist

Hobby: Kayaking, Photography, Skydiving, Embroidery, Leather crafting, Orienteering, Cooking

Introduction: My name is Twana Towne Ret, I am a famous, talented, joyous, perfect, powerful, inquisitive, lovely person who loves writing and wants to share my knowledge and understanding with you.