Nane
Nane

Reputation: 403

how to authenticate user with email only passport.js?

I am trying to authenticate my user with specific flow.

User will enter email for signup and user will be logged in immediately to the account and I will send email confirmation link, with that link user could update password and login to the account.

But i am stuck

I am confused how to signup and login with email only

route.js

  app.post('/get_started', (req, res) => {
         let {email} = req.body;
         let isEmail = emailValidator(email);
         // i will save the user email and try to login
         if(isEmail){
             passport.authenticate('local',{ successRedirect: '/dashboard', failureRedirect: '/' })
         }
    })

Startegy.js

import LocalStrategy from 'passport-local'

export default passport => {

    passport.use('local',new LocalStrategy( (email, done) => {

        console.log(email,'Inside Passport')

    }));

}

Upvotes: 4

Views: 2261

Answers (2)

Anand Undavia
Anand Undavia

Reputation: 3543

Before I demonstrate how to achieve what you have ask for, I would strongly suggest against re-engineering the login and signup systems.These systems have been around since forever and for the most cases, it is best to stick to the traditional ways of doing so.

With that said,

To achieve the functionality that user can login using just email, you can use the passport-custom module which will let you write your own logic to login user.

Register the strategy:

passport.use(
    "my-custom-strategy",
    new CustomStrategy(function(req, callback) {
        const email = req.body.email;
        User.exists(email).then(exists => {
            const info = {};
            if (exists) {
                // user has already entered password,
                // redirect to some page and where user can enter the password
                info.passwordRequired = true;
            } else {
                // user has not entered password,
                // add the user to db
                // send the link and let them login for now
                info.sendEmailLink = true;
            }
            return callback(null, { email }, info);
        });
        callback(null, user);
    })
);

I assume that User.exists(email) method is available which will return the promise that will either resolve to true or false based based of whether the email exists. The info object will be used in the controller to implement the actual logic.

app.use("/get_started", (req, res, next) => {
    let { email } = req.body;
    let isEmail = emailValidator(email);
    // i will save the user email and try to login
    if (isEmail) {
        passport.authenticate("my-custom-strategy", (err, user, info) => {
            if (info.passwordRequired) {
                // you can use custom cookie to set the user.email
                // and access it later to fully authenticate the user
                // using the email and password
                res.redirect("/enter_password");
            } else if (info.sendEmailLink) {
                // logic to send the email
                // once the email sent, redirect to dashboard
                res.redirect("/dashboard");
            }
        })(req, res, next);
    }
});

Upvotes: 1

Svetoslav Petrov
Svetoslav Petrov

Reputation: 1198

Here is an example which additionaly uses sequelize and bcrypt:

route.js:

app.post('/get_started', passport.authenticate('local'), (req, res) => { 
    // Do stuff after successful login here
}

Strategy.js:

passport.use(
    'local',
    new LocalStrategy(
        {usernameField: 'email'},
        (email, passwordCleartext, done) => 
            User.findOne({where: {email: email}})
                .then(user => 
                    !user ?
                        done('Unauthorized', false, {message: 'Incorrect email or password.'}) :
                        bcrypt.compare(passwordCleartext, user.password)
                            .then(res => 
                                res ? 
                                    done(null, user, {message: 'Logged In Successfully'}) :
                                    done('Unauthorized', false, {message: 'Incorrect email or password.'}))
                            )
                .catch(() => done('Unauthorized', false, {message: 'Incorrect email or password.'}))
    )
);

Upvotes: 1

Related Questions