Why the (req, res, function() {...}) immediately after passport.authenticate('local') when registering a new user with passport-local-mongoose? - passport.js

Following the The Complete 2023 Web Development Bootcamp-course by the App Brewery on Udemy, having progressed to lesson 386: Using Passport.js to Add Cookies and Sessions, I am wondering what the purpose is of (req, res, function() {...}) immediately after passport.authenticate('local') for registering a new user using passport-local-mongoose.
Source where the teacher has it from: https://mherman.org/blog/user-authentication-with-passport-dot-js/
(referenced in the documentation for passport-local-mongoose)
In context from the above link:
app.post('/register', function(req, res) {
Account.register(new Account({ username : req.body.username }), req.body.password, function(err, account) {
if (err) {
return res.render('register', { account : account });
}
passport.authenticate('local')(req, res, function () {
res.redirect('/');
});
});
});
Why isn't it written as:
...
passport.authenticate('local', function(req, res) {
res.redirect('/');
});
...
with the callback included as an argument?
Trying approaches that adhere to what I've become familiar with thus far, found in the Passport.js documentation and the passport-local-mongoose documentation, the user gets registered, but the redirection to the secrets-page is not done, instead having the page's load-indicator run continuously without changing from the register-page.
The route for reference below.
app.route("/register").get(function (req, res) {
res.render("register");
}).post(function (req, res) {
User.register({username: req.body.username}, req.body.password, function (err, user) {
if (err) {
console.log(err);
res.redirect("/register");
}
//WORKS: The App Brewery
//Based on: https://mherman.org/blog/user-authentication-with-passport-dot-js/#add-registerjade, 2022-12-25
passport.authenticate("local")(req, res, function () {
res.redirect("/secrets");
});
//DOESN'T WORK: Passport documentation on authentication
// passport.authenticate(
// "local",
// {failureRedirect: "/", failureMessage: true},
// function (req, res) {
// res.redirect("/secrets");
// });
//DOESN'T WORK: passport-local-mongoose documentation
// const authenticate = User.authenticate();
// authenticate(req.body.username, req.body.password, function (err, result) {
// if (err) {
// console.log(err);
// } else {
// res.redirect("/secrets");
// }
// });
});
});

Related

How do i test postman when i have passport authentication

Im trying to test using postman but i have a passport authentication which is blocking me from testing as it will redirect me to the login screen it is not authenticated.
How i can get a token or authenticate myself in postman to be able to test
I have tried to use /auth/local in postman but it just returns that i cant get the route
Passport.js
var LocalStrategy = require('passport-local').Strategy;
var { User } = require('../model/user.js');
var bcrypt = require('bcrypt');
module.exports = function (passport) {
passport.use(new LocalStrategy(function (username, password, done) {
let query = { username: username };
User.findOne(query, function (err, user) {
if (err) throw err;
if (!user) {
return done(null, false,{ message: 'No user found' });
}
bcrypt.compare(password, user.password, function (err, isMatch) {
if (err) throw err;
if (isMatch) {
return done(null, user);
} else {
return done(null, false,{ message: 'Wrong password' });
}
});
});
}));
passport.serializeUser(function (user, done) {
done(null, user.id);
});
passport.deserializeUser(function (id, done) {
User.findById(id, function (err, user) {
done(err, user);
});
});
}
Route.js
router.get('/register', function (req, res) {
res.sendFile(__dirname + "/views/register.html");
});
router.post('/register', async (req, res) => {
var data = req.body;
var salt = await bcrypt.genSalt(10)
var hashedpw = await bcrypt.hash(data.password, salt)
const newUser = await User.create({
name: data.name,
email: data.email,
username: data.username,
password: hashedpw,
});
newUser.save();
req.flash('success', 'You are now registered and can log in');
res.redirect('/');
});
router.get('/login', function (req, res) {
res.locals.success = req.flash('success');
res.locals.error = req.flash('message');
res.render(__dirname + "/views/login.ejs");
});
router.post('/login', async (req, res, next) => {
passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/login',
failureFlash: true
})(req, res, next);
});
router.get('/logout', async (req, res) => {
req.logout(function (err) {
if (err) { return next(err); }
req.flash('success', 'You are logged out');
res.redirect("/")
});
});
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return next();
} else {
res.redirect('/login');
}
}
Following this guide:
https://mevelix.com/articles/postman-auth-for-laravel,4
you have to create the Command:
php artisan make:command DevPostman
then in the newly created class, copy the content it is showed in the link,
inside the class namespace App\Console\Commands\DevPostmanCommand
Then you can execute the command:
php artisan dev:postman web
in this way you are creating a simulated session.
This is my ouput, for example:
you paste this output directly in PostMan, inside the Tab Pre-Request Scripts:
In this way you are allowed to avoid the login inside Postman, because you are simulating a session.
See the first link to have the complete code of the DevPostmanCommand class.

How to pass Data Between multiple routes in express?

app.post("/login", passport.authenticate("local",), function (req, res) {
const user = new Model({
username: req.body.username,
password: req.body.password,
});
req.login(user, function (err) {
if (err) {
console.log("wrong password");
} else {
passport.authenticate("local")(req, res, function () {
res.redirect("/admin");
});
}
});
});
app.post("/admin", function (req, res) {
Model.findOne({username: "siddharth"}).exec(function(err, foundList){
if(foundList)
{
const list = new linkModel({
linkTitle: req.body.linkTitle,
linkUrl: req.body.linkUrl,
});
foundList.links.push(list);
foundList.save();
res.redirect("/admin");
}
else
{res.send("redirect to home page and then login");
res.redirect("/login");
}
});
});
How can i pass the username when authenticated from login routeto other route(admin) where mongoose query is defined findone?
As i have defined it explicitly.
Or i simple terms how can i pass the data among routes ?
You can't. Instead use a middleware to do the checks you want and pass on the result to another middleware or return the response in case of error.

Registration of New Users using passport

I'm working on a freecodecamp challenge. I'm trying to register a user and login the same user but couldn't do it successfully.
I've tried various methods by changing my code a couple of times but still was not successful.
// Register
app.route('/register').post((req, res, next) => {
db.collection('users').findOne({ username: req.body.username }, function (err, user) {
if(err) {
console.log('error')
next(err);
} else if (user) {
console.log('redirect to home-page')
res.redirect('/');
} else {
db.collection('users').insertOne({username: req.body.username, password: req.body.password}, (err, doc) => {
if(err) {
console.log('error after recored')
res.redirect('/');
} else {
console.log('error with user', doc);
next(null, user);
}
}
)
}
})},
passport.authenticate('local', { failureRedirect: '/' }), (req, res, next) => {
res.redirect('/profile');
});
I have the complete code here for your reference.
I should be able to register and it directs me to my profile.
Login successfully and redirect to the profile.
In the code that you have referenced, you seem to have a typo in the Passport local strategy handler.
passport.use(new LocalStrategy(
function(username, password, done){
db.collection('user').findOne({username: username}, (err, user) => {
The collection here should be users as the Register route creates a entry in the users collection.

Node.js passport custom callback

I am using passport for my node.js app.
When I want to authenticate users local, I can simply do it
function local(req, res) {
req._passport.instance.authenticate('local', function(err, user, info) {
if(err) {
return workflow.emit('exception', err);
}
// and so on
res.end('some data');
}
}
But when I want to use facebook strategy, I must use redirectUrls like this.
function signinFacebook(req, res, next) {
req._passport.instance.authenticate('facebook')(req, res, next);
}
function facebookCallback(req, res, next) {
req._passport.instance.authenticate('facebook', {
successRedirect: '/',
failureRedirect: '/'
})(req, res, next);
}
This way I cant send with response data, that I am sending on local strategy.
Can anyone help me to fix it. I want not give success and failure Redirects, I want to call some function if all goes well like on local strategy.
I've found this in Passport's documentation, it may help.
app.get('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err); }
if (!user) { return res.redirect('/login'); }
req.logIn(user, function(err) {
if (err) { return next(err); }
return res.redirect('/users/' + user.username);
});
})(req, res, next);
});
Note that when using a custom callback, it becomes the application's responsibility to establish a session (by calling req.login()) and send a response.

Use request and passport npm login account

I am using nodejs for a project,now I want login my account with passport npm,but not from webpage,from request post method,can it be done?
main code like this:
router.post('/login',function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err); }
if (!user) { return res.json(null); }
req.logIn(user, function(err) {
if (err) { return next(err); }
//return res.redirect('/'); redirect not work
});
})(req, res, next);
});
router.get('/check',function(req, res, next) {
request.post({
url:'http://localhost/login',
headers:{
'Content-Type': 'application/x-www-form-urlencoded'
},
form:{
username:'myname',
password:'mypassword'
}},function(err,httpRes,body){
//do here...?
return res.redirect('/');
});
});
When I call "check" with get method and use the correct username/password,I can print out the user data from database in "login" method,but lost the user session when it redirect home page.Any suggestion?
It's not redirecting the user when they GET /check because the POST request to /login in /check is getting redirected itself, not the actual user. Also making internal requests to internal webpages isn't the best solution for logging in. I suggest creating login() middleware like so:
// Don't forget to set req.body.username and req.body.password when calling login().
var login = function login(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err); }
if (!user) { return next(); }
req.logIn(user, function(err) {
if (err) { return next(err); }
return next(null);
});
})(req, res, next);
};
And then calling it appropriately:
router.post('/login', login, function(req, res, next) {
if (req.user) {
console.log('We logged in successfully!');
res.redirect('/');
} else {
res.json(null);
}
});
router.get('/check', function(req, res, next) {
if (!req.user) {
login(req, res, function(err) {
if (err) {
return next(err);
}
if (!req.user) {
// No user, do some error handling.
} else {
// We have the user, do some custom stuff...
}
res.redirect('/');
});
} else {
// User is logged in already, do some other custom stuff...
}
});
You can check if a user is logged in by checking if req.user exists.

Resources