Passport authentication not being called - node.js

I have code in router
router.post('/auth', function(req, res) {
oauth.auth(req, res);
});
correctly hitting
accesstokenController.auth = function(req, res) {
console.log('Here auth called');
passport.initialize(), passport.authenticate(
'local', {
session: false,
scope: []
},(req,res)), serialize, generateToken, respond
};
(req,res) added after getting a link which suggest this
I belive it should now call
passport.use(new Strategy(
function(username, password, done) {
console.log('Here pass called with ' + username + ' - ' + password);
db.authenticate(username, password, done);
}
));
But it never call and timeout occured.
If Id drectly call like this
app.post('/auth', passport.initialize(), passport.authenticate('local', { session: false,scope: [] }), serialize, generateToken, respond);
this is OK,
In my above method
accesstokenController.auth = function(req, res) {
console.log('Here auth called');
passport.initialize(), passport.authenticate(
'local', {
session: false,
scope: []
},(req,res)), serialize, generateToken, respond
};
I have just created a separate method and called it from router page, rather than calling this itslef
What I am missing
Other code
const db = {
updateOrCreate: function(user, cb) {
cb(null, user);
},
authenticate: function(username, password, cb) {
console.log('Here called');
User.findOne({ username: username,
password: password }).exec(function (err, user) {
if (err) {
cb(null,null);
}
else {
cb(null,user);
}
});
}
}
function serialize(req, res, next) {
console.log('Here pass called with ser ');
db.updateOrCreate(req.user, function(err, user) {
if (err) {
return next(err);
}
// we store information needed in token in req.user again
req.user = {
id: user.id
};
next();
});
}
function generateToken(req, res, next) {
req.token = jwt.sign({
id: req.user.id,
}, SECRET, {
expiresIn: TOKENTIME
});
next();
}
function respond(req, res) {
res.status(200).json({
user: req.user,
token: req.token
});
}
I have many link related to that but did not manage to solve this

Your strategy needs to return done() without which the Strategy doesn't know when it's completed, thus resulting in a timeout.
Difficult to say if this is the exact problem without further context.

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.

Internal OAuth Error: Failed to fetch user profile NodeJs with passport-google-oAuth2

Here is my code to authenticate user based on google email :
router.use(passport.initialize());
passport.serializeUser((user, done) => {
done(null, user);
});
passport.deserializeUser((user, done) => {
done(null, user);
});
passport.use(new GoogleStrategy({
clientID: config.googleClientID,
clientSecret: config.clientSecret,
callbackURL: host + "/google-login/callback"
}, (accessToken, refreshToken, profile, done) => {
const user = {}
user.name = profile.displayName;
user.email = profile.emails[0].value;
user.photo = profile.photos[0].value;
return done(null, user);
}
));
router.get('/', passport.authenticate('google', { scope: ['profile', 'email'] }));
router.get('/callback', passport.authenticate('google', { failureRedirect: '/signup' }),
async (req, res) => {
await register(req, res);
res.redirect('/google-login/popup');
});
router.get('/popup', (req, res, next) => {
res.render('login/popup-close');
});
router.get('/popup-done', authorize(), async(req, res, next) => {
const account = await getAccount({ id: req.user.id, include: ['firstImpression', 'role'] });
// if(req.user.role === Role.Admin) return res.redirect(`/accounts/admin5852`);
const { section, data } = req.query;
if(section == 'checkout') {
redirect();
} else {
if(account.firstImpression) {
account.firstImpression = false;
await account.save();
res.redirect(`/accounts/dashboard#section=guide`);
} else {
redirect();
}
}
function redirect() {
if(section == 'undefined') {
res.redirect(`/accounts/dashboard`);
} else {
res.redirect(data ? `/accounts/dashboard#section=${section}&data=${data}` : `/accounts/dashboard#section=${section}`);
}
}
});
I get this error sometimes Not all the times but sometimes and this makes it really hard to understand the bug:
{"name":"InternalOAuthError","message":"Failed to fetch user profile","oauthError":{"errno":-101,"code":"ENETUNREACH","syscall":"connect","address":"2a00:1450:4017:808::200a","port":443}}
How can I debug this? How to fix this?

Passport req.logIn never call serializeUser

I am trying to signUp and login with passport for my project but i am new in passport and i have some isuues, i have a sequelize database that have (name,password,email), when i post /users it it never go to serializeUser and it load forever.
here is my post request for signUp:
router.post('/', async function(req, res, next) {
console.log(req.body, 'create new user');
const user = await User.create(
{ Name: req.body.Name, Password: req.body.Password, Email: req.body.Email }
);
const userss = await User.findOne({ where: { Email: req.body.Email } });
console.log(user, userss);
console.log('1');
try {
console.log('inserting');
await user.save(function(err) {
console.log(user.dataValues.id);
req.logIn(user.dataValues.id, function(err) { // here is the problem!
console.log('logIn');
console.log('inserted');
return res.redirect('/');
});
console.log('inserted?');
});
} catch (err) {
console.log(err);
return res.render('users/new', { user, error: req.flash('error') });
}
});
and here is my passport:
passport.serializeUser(function(user, done) {
console.log(user);
console.log('serialized1');
done(null, user);
console.log('serialized2');
return;
});
passport.deserializeUser(async function(id, done) {
console.log('here0');
const user = await User.findByPk(id);
console.log('here2');
done(null, user);
console.log('here4');
});
and here is the login rout:
router.post('/',
passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/sessions',
failureFlash: true
}),
function(req, res, next) {
console.log('new user connected');
socketio.io.sockets.emit('msg', `New user connected: ${req.user}`);
}
);
It appears that you have both two routes pointing to the same path.
I would recommend updating the login routes path.
router.post('/login',
passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/sessions',
failureFlash: true
}),
The issue described in the title also happens with Passport v0.6.0 due to this issue in the library. So req.login() silently does nothing, serializeUser() never gets called, and moving back to Passport v0.5.3 solves the issue.

How to access data sent via next parameter in express middleware

I am running an express server and came across a middleware problem with passport authenticate which is something like this
passport.use('google', new GoogleStratergy({
clientID: "",
clientSecret: "",
callbackURL: "/Users/auth/google/callback",
passReqToCallback : true
}, (request, accessToken, refreshToken, profile, done) => {
Users.findOne({ UserID: profile.id }, function (err, user) {
if (err){
return done(err);
}
if (!user){
var User = new Users({});
User.setPassword(Math.random().toString(36).substring(5));
var jwt = User.generateJWT();
User.save()
.then(() => {
return done(null, User, jwt);
})
.catch(err => {
return done(err);
})
}
else {
var jwt = user.generateJWT();
return done(null, user, jwt);
}
});
}
));
just now I don't know how to access the objects passed in the done function when using the middleware in another route like this.
router.get('/something', passport.authenticate('google'), (req, res, next) => {
// Now I need to access User and jwt object here passed with done()
res.send("whatever");
})
Have you checked the req object? do this
router.get('/something', passport.authenticate('google'), (req, res, next) => {
console.log(req.user)
console.log(req.jwt)
// Now I need to access User and jwt object here passed with done()
res.send("whatever");
})

req object in passport.authenticate

I am using passportjs for authentication on my server. I am using the following code:
exports.auth = function(req, res, next){
passport.authenticate('bearer', { session: false })(req, res, next);
};
passport.use(new BearerStrategy(
function(token, done) {
User.findOne({ token: token }, function (err, user) {
if (err) { return done(err); }
if (!user) {
return done(null, false);
}
return done(null, user, { scope: 'read' });
});
}
));
Is there a way to access the req object in passport.use? This was I can get the user ip address and check for eventual attacks.
The comments in the example suggest that you can pass an object { "passReqToCallback": true } to make the req callback available in the callback function. Which can be accessed as
function(req, token, done){//rest of the function body}
So initialize passport.use as
passport.use(new BearerStrategy({ "passReqToCallback": true },
function(req, token, done) {
});
and you should have req in the callback.

Resources