Automating user login with node.js and passport.js: A step-by-step guide

My login application is built using node.js and passport.js, with the session being maintained using express-session and connect-mongo. I need to ensure that users are redirected to the home page upon accessing the URL, only sending them to the login page if they have not logged in before. How can I achieve this functionality?

Login.js

module.exports = function(passport){

    passport.use('login', new LocalStrategy({
            passReqToCallback : true
        },
        function(req, username, password, done) { 
            // check in mongo if a user with the username exists or not
            User.findOne({ 'username' :  username }, 
                function(err, user) {
                    // In case of any error, return using the done method
                    if (err)
                        return done(err);
                    // Username does not exist, log the error and redirect back
                    if (!user){
                        console.log('User Not Found with the username '+username);
                        return done(null, false, req.flash('message', 'User Not found.'));                 
                    }
                    // User exists but wrong password, log the error 
                    if (!isValidPassword(user, password)){
                        console.log('Invalid Password');
                        return done(null, false, req.flash('message', 'Invalid Password')); 
                    }
                        // User and password both match, return user from the done method
                    // which will be treated like success
                    return done(null, user);
                }
            );

        })
    );


    var isValidPassword = function(user, password){
        return bCrypt.compareSync(password, user.password);
    }

}

Signup.js

module.exports = function(passport){

    passport.use('signup', new LocalStrategy({
            passReqToCallback : true 
        },
        function(req, username, password, done) {

            findOrCreateUser = function(){
                // find a user in Mongo with the provided username
                User.findOne({ 'username' :  username }, function(err, user) {
                    // In case of any error, return using the done method
                    if (err){
                        console.log('Error in SignUp: '+err);
                        return done(err);
                    }
                    // already exists
                    if (user) {
                        console.log('User already exists with the username: '+username);
                        return done(null, false, req.flash('message','User Already Exists'));
                    } else {
                        // if there is no user with that email
                        // create the user
                        var newUser = new User();

                        // set the user's local credentials
                        newUser.username = username;
                        newUser.password = createHash(password);
                        newUser.email = req.param('email');
                        newUser.firstName = req.param('firstName');
                        newUser.lastName = req.param('lastName');

                        // save the user
                        newUser.save(function(err) {
                            if (err){
                                console.log('Error in Saving user: '+err);  
                                throw err;  
                            }
                            console.log('User Registration successful');    
                            return done(null, newUser);
                        });
                    }
                });
            };
            // Delay the execution of findOrCreateUser and execute the method
            // in the next tick of the event loop
            process.nextTick(findOrCreateUser);
        })
    );

    // Generates hash using bCrypt
    var createHash = function(password){
        return bCrypt.hashSync(password, bCrypt.genSaltSync(10), null);
    }

}

index.js

var isAuthenticated = function (req, res, next) {
    // if the user is authenticated in the session, call the next() to call the next request handler 
    // Passport adds this method to the request object. A middleware is allowed to add properties to
    // request and response objects
    if (req.isAuthenticated())
        return next();
    // if the user is not authenticated then redirect them to the login page
    res.redirect('/');
}

module.exports = function(passport){

    /* GET login page. */
    router.get('/', function(req, res) {
        // Display the Login page with any flash message, if any
        res.render('index', { message: req.flash('message') });
    });

    /* Handle Login POST */
    router.post('/login', passport.authenticate('login', {
        successRedirect: '/home',
        failureRedirect: '/',
        failureFlash : true  
    }));

    /* GET Registration Page */
    router.get('/signup', function(req, res){
        res.render('register',{message: req.flash('message')});
    });

    /* Handle Registration POST */
    router.post('/signup', passport.authenticate('signup', {
        successRedirect: '/home',
        failureRedirect: '/signup',
        failureFlash : true  
    }));

    /* GET Home Page */
    router.get('/home', isAuthenticated, function(req, res){
        res.render('home', { user: req.user });
    });

    /* Handle Logout */
    router.get('/signout', function(req, res) {
        req.logout();
        res.redirect('/');
    });

    return router;
}

Answer №1

User session information is commonly stored on the client side using cookies or local storage. Your user interface application needs to verify the presence of this data and direct the authenticated user to a specific URL without needing to interact with a server.

Upon receiving the initial request from the UI (with data retrieved from the cookie or local storage), you can validate this data on the server. If the data is not valid, you have the option to refresh the session data and provide it back to the user, or log out the user depending on the workflow in place.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Heroku - Node.js Application Issue

After successfully deploying the app using github, I encountered an issue when trying to access the website: Application Error An error occurred within the application preventing your page from being served. Please try again after a few moments. If y ...

When the button is clicked, bind the value to an object using the specified key in

I'm fairly new to Vue and I'm looking to generate buttons based on my data and show their information when clicked. The 'pets' object contains keys for id and info. (My actual data is more extensive and my code is a bit more complex, bu ...

One of the three identical paths in Node.JS is experiencing issues

I'm brand new to Node.js and currently working on creating a backend api for a project. I have 3 routes in my application: societies, users, and emails. //module for email functionality emailsModule = require('./api/routes/emails')(co ...

Having trouble executing react-native project using the command "npx react-native run-android"

Hey there! I've been working on a react-native project for quite some time now and everything was going smoothly until yesterday. I encountered an error when running the command npx react-native run-android in Metro before the project had fully execut ...

Having trouble making API calls from the NextJS endpoint

While attempting to access an external API endpoint in NextJS, I encountered the following error message: {"level":50, Wed Jan 24 2024,"pid":4488,"hostname":"DESKTOP-S75IFN7","msg":"AxiosError: Request ...

Is there a way to efficiently update specific child components when receiving data from websockets, without having to update each child individually?

Currently, my frontend requires updated data every 2 seconds. The process involves the frontend sending an init message to the backend over a websocket. Upon receiving this message, the backend initiates an interval to send the required data every 2 second ...

Verifying Node.js request parameters against database field requirements

I am currently in the process of constructing a REST API using node, express, and MongoDB with mongoose. My goal is to implement validation for post requests. Below is an example of how I have defined a schema: var CategorySchema = new Schema({ name: ...

Trouble arises when attempting to remove an object using a combination of Node.JS, Mongoose, MongoDB, and

In my setup, I have two collections: one is called subcategories and the other is called categories. The categories collection includes a field known as subcategories which is an array containing the ids of the subcategories from the subcategories collecti ...

Image Placement Based on Coordinates in a Graphic Display

Placing dots on a map one by one using CSS positions stored in arrays. var postop =[{'top':'23'},{'top':'84'},{'top':'54'},{'top':'76'},{'top':'103'}]; var ...

Ensure that each function is completed before proceeding to the next one

I've encountered an issue with my react app. After a user submits a form, I need a modal to open and the user's response to be stored in state. Then, based on this response, I have to execute some business logic before finally submitting the form ...

Elastic Beanstalk on AWS is unable to install a private Node.js module that is hosted on Bitbucket

Attempting to launch a node.js application on Elastic Beanstalk. The main package.json contains a private module hosted on Bitbucket. "dependencies": { "my-module": "git+https://<API-KEY>:<a href="/cdn-cgi/l/email-protection" class="__cf_email_ ...

The Google Maps API has been successfully initialized, however, it is experiencing difficulties being displayed on the webpage

I have been successfully using a custom Google API on various web pages. However, I encountered an issue where the map API loads successfully but is not displaying on a specific web page. Below are the relevant code snippets: <html> <head> &l ...

When utilizing Sequelize to insert data, PostgreSQL has the capability to return an additional table column

Encountered an error while attempting to add a new category: error: column "image" does not exist sql: 'INSERT INTO "Categories" ("id","createdAt","updatedAt") VALUES (DEFAULT,$1,$2) RETURNING " ...

Display a specific tab section upon clicking using jQuery or JavaScript

Hello everyone! I am completely new to JavaScript. I have added a tab slider to my HTML with 3 categories in the tab menu: All, Creative, and Branding. How can I show a div after clicking on one of the list items? I have assigned classes to the list items ...

Can you assist in resolving this logical problem?

exampleDEMO The code above the link demonstrates how to control input forms based on a button group selection. In this scenario, when a value is inputted on the 'First' Button's side, all input forms with the same name as the button group ...

Managing Promise rejections within Express middleware

Is there a way to catch unhandled Promises Rejections using middleware in order to access the Request and Response objects of the request? I've written some code, but it seems that the middleware or process.on function is not being triggered when an u ...

Reorganize code in JavaScript and TypeScript files using VSCode

Is there a way to efficiently organize the code within a .js / .ts file using Vscode? Specifically, when working inside a Class, my goal is to have static variables at the top, followed by variables, then methods, and so on automatically. I did some resea ...

Leveraging AngularJS ngBind with a JavaScript object

Within the given string, integrating a javascript object and embedding it into an ngBinding does not result in proper evaluation. I have a string where I want to incorporate a specific part of a javascript object and am transitioning to Angular for its use ...

My attempt to use the Redux method for displaying data in my testing environment has not yielded

I've been attempting to showcase the data in a Redux-friendly manner. When the advanced sports search button is clicked, a drawer opens up that should display historical data when the search attributes are selected. For this purpose, I implemented the ...

I'm having trouble with create-react-app and it seems to be stalled indefinitely. Any advice on how to resolve this issue

After completing a React course, I wanted to start practicing by creating a project using create-react-app. However, I'm facing difficulties as the installation process gets stuck and displays error messages that are hard for me to understand. I&apos ...