Intercepting flash message - node.js

I am using Passport authentication with 'local' strategy for my application. I want the user to be able to know if the username and password entered by user is invalid and if valid then redirect to dashboard.
This is how i am authenticating the user:
router.post('/login', passport.authenticate('local', {failureRedirect: '/login', failureFlash: 'Invalid username or password.'}), function(req, res, next){
res.redirect('/users/dashboard');
});
Redirect part works fine, but the user enters invalid user/pass the flash message in failureFlash: 'Invalid username or password.' dosent show up on the login page.
This is how i handle my login route:
router.get('/login', function(req, res, next) {
res.render('pages/login', {'title' : 'VoteCenter - Login', message: req.flash('message')});
});
What do i need to use in req.flash('??????') to intercept the flash mesaage coming from failureFlash?

You can get message through req.flash('error')(default)
also you can pass failureFlash object with your custom message name like it:
failureFlash: { type: 'authError', message: 'Invalid username or password.'}
then get message req.flash('authError')

Related

Prevent User from logging again in passportjs if they are authenticated once?

I am using PassportJS, and signup and login functions are working quite smooth.
The only problem I am facing with PassportJS (I am using sessions too), that even when the user had logged in, they can again go back to the signup/login url and do signup and/or login back!
This is tempting me. If anyone has a fix/suggestion, please put it down.
UPDATE - 1
Glimpse of myroutes.js: (Using PassportJS along with connet-ensure-login.
app.get('*', function(req, res, next) {
if (req.url.indexOf('/users/login') < 0 &&
req.url.indexOf('/users/signup') < 0) {
req.session.returnTo = null;
}
next();
});
// =====================================
// HOME PAGE (with login links) ========
// =====================================
app.get('/', sabSettings, function(req, res) {
Setting.findOne(function(err, setting) {
if (err)
throw err;
// console.log(setting);
res.render('index', { title: 'eduBird | Reach the glory', setting: req.setting }); // load the index file
});
});
// =====================================
// LOGIN ===============================
// =====================================
// show the login form
app.get('/login', sabSettings, function(req, res) {
// render the page and pass in any flash data if it exists
res.render('login', {
message: req.flash('loginMessage'),
errors: req.flash('error'),
title: 'Login | eduBird',
setting: req.setting
});
});
// process the login form
app.post('/login', passport.authenticate('local-login', {
successReturnToOrRedirect: '/loggedin',
failureRedirect: '/login',
failureFlash: true
}));
// =====================================
// SIGNUP ==============================
// =====================================
// show the signup form
app.get('/signup', sabSettings, function(req, res) {
// render the page and pass in any flash data if it exists
process.nextTick(function() {
res.render('signup', {
message: req.flash('signupMessage'),
errors: req.flash('error'),
title: 'Register | eduBird',
setting: req.setting
});
});
});
// process the signup form
app.post('/signup', passport.authenticate('local-signup', {
successReturnToOrRedirect: '/profile/welcome',
failureRedirect: '/signup',
failureFlash: true
}));
You have not created any sort of access control, but don't worry we will first go through how Passport works and use this to address the problem.
When the user submits a login form, a POST request to our specified path is made resulting in the execution of the passport.authenticate.
The authenticate middleware for that route is configured to handle the local strategy, passport will invoke your implementation of the local strategy.
If an error occurs while interacting with our database, we invoke done(err). Otherwise if the user is not found or the passwords do not match, we invoke done(null, false). If successful we invoke done(null, user).
Calling done will return us to the passport.authenticate and the corresponding redirect will be executed.
At this point, if the sign-in was successful, the user object (from done(null, user)) is attached to the request and you can access the user object through req.user.
The main idea is if the user object is not attached to the request it means the user is not logged in, so we can control our application behaviour for logged in
users with req.user. For example:
// If the user object does not exist it means the user is not logged in
if (!req.user) {
res.render('signin');
} else {
// If the user object exists, the user is logged in and if they try to log in we redirect them to the home page
return res.redirect('/');
}
I hope this helps.

Node & Passport : stay on the same page after login

With Passport and Express, I succeed handling user session. Because I have some pages, that do not need be logged to be viewed, a user can login in many page.
How should I handle passport.authenticate to redirect on the current page, augmented with user data.
app.post('/login',
passport.authenticate('local', { successRedirect: '/',
failureRedirect: '/login',
failureFlash: true })
);
Maybe a custom callback with a res.send(req.user). As I'm completely not familiar, i just advises on this.
The user info will be put on the req.user "by passport"
app.post('/login',
passport.authenticate('local-login', {
successRedirect : 'back', // redirect back to the previous page
failureRedirect : 'back', // redirect back to the previous page
failureFlash : true
})
);
The keyword backredirect to previous page.

Correct Authentication Pattern using Passport.js

It seems the Passport docs suggest using a pattern such as:
app.get("/my/protected/resource", passport.authenticate("local"), function(req, res){
res.json({my:"protected resource"});
});
as the standard way to protect resources after authentication. However, as I have tried this strategy repeatedly, it has repeatedly given me 401 - Unauthorized. Rather, a middleware solution such as the following worked:
exports.loggedIn = function(req, res, next) {
console.log('Checking credentials...');
if(req.isAuthenticated()){
next();
} else {
res.redirect("/");
}
};
This, however, is either not found, or is not made prominent in the docs. Which of these two are the standard and correct way of protecting resources using passport.js?
If you are using sessions, I generally use this type of pattern:
app.get('/resource', passport.authenticate('local', {
successRedirect: '/success',
failureRedirect: '/login',
failureFlash: 'Invalid username or password'
}))
as shown http://passportjs.org/guide/authenticate/
If you want the response in the same function:
app.get('/resource', passport.authenticate('local', {
failureRedirect: '/login',
failureFlash: 'Invalid username or password'
}), function(req, res){
res.json({my:"protected resource"});
})
If you want to be redirected to "/" (as your second example does) rather than getting a 401 (the default behavior) when trying to access a protected resource unauthenticated, using passport.authenticate, you can use the redirect options, as specified in the second section of the page in the docs that you linked:
app.get("/my/protected/resource",
passport.authenticate("local", {failureRedirect: '/' }),
function(req, res){
res.json({my:"protected resource"});
});

More Passport.js woes - hangs on form submission

I am setting up what I thought would be the simplest auth possibly - a site loads on a log in screen, user enters credentials in a form, on submission I am using Passport.JS and Sequelize to check the credentials. Most all of this is copied from various tutorials, or the Passport website itself.
No matter what I do, change or attempt though, the site just hangs as soon as I click the form submit button. In the dev tools network tab I just shows the post request to /login as pending.
To eliminate all possible added problems, I stripped out Sequelize, and used hard coded users, ala the local use example on the passport github page. Still, no change, to Sequelize was not the problem.
I'm sure it's something dumb. I've tried the obvious solutions, like making sure my form was sending 'username' and 'password'.
My form looks like this:
form(method="post", action="/login")
fieldset
legend Please Log In
label(for="username") Username:
input#username(type='text', name="username", autocomplete="off")
label(for="password") Password:
input#password(type='password', name="password")
button#login(type="submit") Log In
In node my app.js uses a router, which includes this:
var login = require('../app/controllers/login');
app.get('/', login.index);
app.post('/login', login.auth);
The page load ok on the get request. On post it directs to this:
exports.auth = function (req, res, next) {
console.log(req.body);
passport.authenticate('local', {
successRedirect: '/home',
failureRedirect: '/',
failureFlash: true
});
};
The console.log(req.body) comes up fine, showing the form values, so we are ok to that point. But nothing after. This is the last part:
passport.use(new LocalStrategy(
function(username, password, done) {
console.log('local strat invoked');
findByUsername(username, function(err, user) {
if (err) { return done(err); }
if (!user) { return done(null, false, { message: 'Unknown user ' + username }); }
if (user.password != password) { return done(null, false, { message: 'Invalid password' }); }
return done(null, user);
});
}
));
I swapped out the code that used Sequelize to check the DB for the user with this findByUsername function (copied and pasted straight from the above mentioned post on the passport github page), but as the console.log('local strat invoked') is never coming up, I'm guessing nothing after that point even matters.
Also includes are the passport.serializeUser and passport.deserializeUser, but I cant imagine those are the problem at the stage where I am stuck.
Any idea what step I am missing to get this working?
Passport is middleware, if you embed it in a route handler function, you need to invoke it:
exports.auth = function (req, res, next) {
console.log(req.body);
passport.authenticate('local', {
successRedirect: '/home',
failureRedirect: '/',
failureFlash: true
})(req, res, next); // <-- NEED TO INVOKE WITH req, res, next
};
or, more simply use it as middleware (which is the recommended approach:
exports.auth = passport.authenticate('local', {
successRedirect: '/home',
failureRedirect: '/',
failureFlash: true
});

nodejs + passport + express 3.0 + connect-flash no flashing?

I'm using a passport-local strategy for authenticate users. I followed the guide given by Jared Hanson and installed connect-flash in order to give flash method to the req object. So one of my request handlers is the following:
app.post('/login',
passport.authenticate('local', {
successRedirect: '/'
, failureRedirect: '/login'
, successFlash: 'Bienvenido'
, failureFlash: 'Credenciales no vĂ¡lidas'
})
);
When the user login fails, it redirects the user to /login again but it doesnt flash anything :/
UPDATE:
I use mongodb for session storage and I see this:
> db.sessions.find()
{ "_id" : "qZ2eiTnx6r9LR25JOz/TGhiJ", "session" : "{\"cookie\":{\"originalMaxAge\":null,\"expires\":null,\"httpOnly\":true,\"path\":\"/\"},\"passport\":{\"user\":\"4ffb5b5db9cc16b615000001\"},\"flash\":{\"error\":[\"Credenciales no vĂ¡lidas\"],\"success\":[\"Bienvenido\"]}}" }
So the messages are inserted into the session object but they aren't pulled out. Should I do something special?
I assume you're pulling the messages out and rendering them in a view? Something like:
app.get('/login', function(req, res){
res.render('login', { message: req.flash('error') });
});

Resources