passport.authenticate() using a Promise instead of a Custom Callback - node.js

passport.authenticate(), how can I define a Promise instead of using a Custom Ballback?
How to used passport.authenticate() is referenced within here:
http://www.passportjs.org/docs/authenticate/
Within this page, there is a section Custom Ballback:
If the built-in options are not sufficient for handling an authentication request, a custom callback can be provided to allow the application to handle success or failure.
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);
});
The Custom Callback is defined as:
function(err, user, info){...}
What I wish to do is replace this Custom Callback with a Promise.
[Promise](resolve, reject)
.then(res => {
})
.catch(err => {
})
How can I do this? Thank you.

You can use the es6-promisify package. It is very easy to use, here is an example:
const {promisify} = require("es6-promisify");
// Convert the stat function
const fs = require("fs");
const stat = promisify(fs.stat);
// Now usable as a promise!
stat("example.txt").then(function (stats) {
console.log("Got stats", stats);
}).catch(function (err) {
console.error("Yikes!", err);
});

Thanks all for your helpful responses #sterling-archer and #el-finito
I had found a related issue within Passport.js Github repository helpful for using Passport to handle passport.authenticate() callback:
"Using node's promisify with passport"
export const authenticate = (req, res) =>
new Promise((resolve, reject) => {
passport.authenticate(
[passport strategy],
{ session: false },
(err, user) => {
if (err) reject(new Error(err))
else if (!user) reject(new Error('Not authenticated'))
resolve(user)
})(req, res)
})

Related

Receiving data from backend returns undefined

In the node.js in the login post endpoint, I get the login data for user. I declare req.user.dataValues in variable userData and I'm trying to access it inside /data endpoint so later I can access it on frontend.
Node.js - localhost:4000
router.post('/login', function (req, res, next) {
passport.authenticate('local', function (err, user, info) {
if (err) {
return next(err)
} else if (!user) {
console.log('message: ' + info.message);
return res.redirect('/login')
} else {
req.logIn(user, function (err) {
if (err) {
return next(err);
}
let userData = req.user.dataValues;
router.get('/data', (req, res) => {
console.log(userData)
res.json({user: userData})
})
res.json({ redirectUrl: "app", user: req.user.dataValues});
});
}
})(req, res, next);
});
I'm using the code below to fetch the data from the /data endpoint from node.js. I don't get any errors but the result is undefined, I wonder why? I need this data in my frontend to build the login etc.
react.js - localhost:3000
Testing = () => {
fetch("http://localhost:4000/data")
.then(res => console.log(res.json()))
.then(
(result) => {
console.log(result)
},
(error) => {
console.log(error)
}
)
}
I ran some test on express. Looks like you are defining your /data endpoint the wrong way.
You are defining the endpoint inside an anonymous function hence it exists only inside the scope of the function.
You should move
router.get('/data', (req, res) => {
console.log(userData)
res.json({user: userData})
})
outside the router.post('/login)

How to initiate session on signup with cookie-session and passport.js?

I have a /register router for signing up a user. I am using cookie-session (which is similar) instead of express-session for simplicity for now.
I am stuck on the part where I need to authenticate a user on sign up. I am confused about the functionality of req.sessions.save() and req.login(). I know req.login() is provided by passport.js, but I don't understand which one provides the req.session object.
I am new to passport.js and have read numerous articles, videos, and StackOverflow questions extensively to build up my knowledge. Honestly, the passport documentation has been quite a pain so far. I am still confused about how session initiation on signup should work. Many articles skipped the signup part. I thus request help on how to do it.
router.post('/register', (req, res, next) => {
console.log(req.body)
User.findOne({email: req.body.email}).then((currentUser) => {
if(currentUser){ // already exists
res.render('login')
} else { // if not, create user in our db
new User({
email: req.body.email
}).save().then((newUser) => {
passport.authenticate('local')(req, res, () => {
//>>>> //**This is where I don't know what to do**
req.session.save((err) => {
if (err) {
return next(err)
}
res.redirect('http://localhost:3000')
})
})
});
}
});
})
const express = require("express");
const router = express.Router();
const passport = require("passport");
router.post("/register", (req, res, next) => {
User.findOne({ email: req.body.email }).then((currentUser) => {
if (currentUser) { // already exists
res.render('login')
} else { // if not, create user in our db
new User({
email: req.body.email
}).save();
}
});
passport.authenticate("local", function (err, user, info) {
if (err) {
return res.status(400).json({ errors: err });
}
if (!user) {
return res.status(400).json({errors:"No user found."});
// or save User : new User({email: req.body.email}).save();
}
req.login(user, function (err) {
if (err) {
return res.status(400).json({ errors: err });
}
req.session.save((err) => {
if (err) {
return next(err)
}
res.redirect('http://localhost:3000')
});
return res.status(400).json({ success: `logged in ${user.id}` });
});
})(req, res, next);
});
module.exports = router;
passport.authenticate('local')(request, response, () => {
req.session.save((err) => {
if (err) {
return next(err)
}
res.redirect('http://localhost:3000')
})
}

JavaScript wait for asynchronous function in if statement [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 5 years ago.
I have a function inside an if statement
isLoggedin() has an async call.
router.get('/', function(req, res, next) {
if(req.isLoggedin()){ <- never returns true
console.log('Authenticated!');
} else {
console.log('Unauthenticated');
}
});
how do i await for isLoggedin() in this if statement?
here is my isLoggedin function in which im using passport
app.use(function (req, res, next) {
req.isLoggedin = () => {
//passport-local
if(req.isAuthenticated()) return true;
//http-bearer
passport.authenticate('bearer-login',(err, user) => {
if (err) throw err;
if (!user) return false;
return true;
})(req, res);
};
next();
});
I do this exact thing using async/await in my games code here
Assuming req.isLoggedIn() returns a boolean, it's as simple as:
const isLoggedIn = await req.isLoggedIn();
if (isLoggedIn) {
// do login stuff
}
Or shorthand it to:
if (await req.isLoggedIn()) {
// do stuff
}
Make sure you have that inside an async function though!
You could promisify your function, like this:
req.isLoggedin = () => new Promise((resolve, reject) => {
//passport-local
if(req.isAuthenticated()) return resolve(true);
//http-bearer
passport.authenticate('bearer-login', (err, user) => {
if (err) return reject(err);
resolve(!!user);
})(req, res);
});
And then you can do:
req.isLoggedin().then( isLoggedin => {
if (isLoggedin) {
console.log('user is logged in');
}
}).catch( err => {
console.log('there was an error:', err);
});
Do not try to keep the synchronous pattern (if (req.isLoggeedin())), as it will lead to poorly designed code. Instead, embrace fully the asynchronous coding patterns: anything is possible with it.

Authentication with passeport in node and angular 2

I'm trying to build an angular 2 application,here is my backend implementation
router.post('/', function(req, res, next) {
passport.authenticate('local', function (err, user, info) {
var error = err || info;
if (error) return res.json(401, error);
if (!user) return res.json(404, {message: 'Something went wrong, please try again.'});
var token = auth.signToken(user._id, user.role);
res.json({token: token});
})(req, res, next)
});
now i want to implement my frontend side with angular 2 but i have no idea how to code services and components.
i tried this
Login(user) {
return new Promise((resolve, reject) => {
this.http.post('http://localhost:3000/auth/local', user)
.map(res => res.json())
});
any solution?
have you looked at this https://github.com/domfarolino/angular2-login-seed
as well as https://github.com/domfarolino/angular2-login-seed/tree/master/src/app/login
Should be fairly easy to implement on you side

how to get passport.authenticate local strategy working with async/await pattern

I've been failing to get passport.authenticate to work at all inside of an async/await or promise pattern. Here is an example I feel should work, but it fails to execute passport.authenticate().
const passport = require("passport");
let user;
try {
user = await __promisifiedPassportAuthentication();
console.log("You'll never have this ", user);
} catch (err) {
throw err;
}
function __promisifiedPassportAuthentication() {
return new Promise((resolve, reject) => {
console.log("I run");
passport.authenticate('local', (err, user, info) => {
console.log("I never run");
if (err) reject(err);
if (user) resolve(user);
}
}
}
Any sage words of wisdom would be greatly appreciated.
Just incase any other tired programmer out there encounters this..
function __promisifiedPassportAuthentication() {
return new Promise((resolve, reject) => {
passport.authenticate('local', (err, user, info) => {
...
})(req, res) // <-- that guy right there
}
}

Resources