I can't work out how best to pass user details (email, name, etc.) to 'logged in' views (I'm using jade).
I'm using passport and have access to session.passport.user in my views but only the user's _id is saved on here, and i've been told it would be bad security practice to persist it locally in the session cookie.
I don't want to have to pass a user object to res.render on each controller that I need the user.
this is how i have sessions setting up locally
app.use(function (req, res, next) {
res.locals.session = req.session;
next(null, req, res);
});
and this is my middleware to check if a user is logged in
function isLoggedIn(req, res, next) {
// if user is authenticated in the session, carry on
if (req.isAuthenticated()) {
return next();
}
// if they aren't redirect them to the home page
res.redirect('/');
}
I have looked at dynamic helpers but I'm using express v3.0.0rc4.
You can use res.locals for this purpose. Anything you put in that object will be available in the view context (unless, of course, it's overridden by a later context). So, for example, you could modify your isLoggedIn middleware thusly:
function isLoggedIn(req, res, next) {
// if user is authenticated in the session, carry on
if (req.isAuthenticated()) {
// obviouisly, don't use static strings...
// get these values from your authentication
// mmechanism
res.locals.user = 'username';
res.locals.userEmail = 'user#domain.com';
return next();
}
// if they aren't redirect them to the home page
res.redirect('/');
}
Related
I'm using PassportJS for handle the access to my application, suppose that the user has logged in, and suppose that these urls:
Login
Register
Welcome
need to redirect the user on dashboard url, only if the user has logged in, how can I do?
This is my authentication middleware:
module.exports = {
ensureAuthenticated: function(req, res, next){
if(req.isAuthenticated()){
return next();
}
res.render('index/forbidden');
}
};
Example:
User go to login
No session
Stay on the page
(already works)
User go to login
Already logged in
Redirect to dashboard
You can create another middleware to redirect if logged in and add it to the routes that don't need login. You are basically doing the opposite.
module.exports = {
ensureAuthenticated: function(req, res, next){
if(req.isAuthenticated()){
return next();
}
res.render('index/forbidden');
},
ensureNOTAuthenticated: function(req, res, next){
if(req.isAuthenticated()){
return res.redirect('/dashboard')
}
return next();
}
};
For routes that need auth:
app.get('/dashboard', ensureAuthenticated, (req,res)=>{...});
For routes that dob't need auth:
app.get('/login', ensureNOTAuthenticated, (req,res)=>{...});
I followed the documentation for passport.js with passport-local: http://www.passportjs.org/docs/authorize/
When I send my users to /login they are authenticated, but nowhere in that document can I find how to authorise my users.
I've tried this, but that gives me a bad request:
router.get('/somepage', passport.authenticate('local'), function(req, res, next) {
});
I'm looking for way to protect all my pages at once. I'm working with Express 4.16 and use different route files to split up my routes.
Sam
you can use middleware with a small trick to switch between strategies
example:
const allowUrl = ['public', 'nonprivate','home'];
const authenticationMiddleware = (whiteList =[]) => (req, res, next) => {
if(whiteList.find(req.baseUrl)) {
next();
}
if (req.isAuthenticated()) {
return next()
}
res.redirect('/');
}
app = express();
app.use(passort.initialize());
app.use(authenticationMiddleware(allowUrl));
app.use(apiRouter);
app.listen(3000, ()=> console.log('hello internet');
you can add your middleware code like below
router.get('/', isAuthenticated, function(req, res) {
//your next function
});
function isAuthenticated(req, res, next) {
// do any checks you want to in here
// CHECK THE USER STORED IN SESSION FOR A CUSTOM VARIABLE
// you can do this however you want with whatever variables you set up
if (req.user.authenticated)
return next();
// IF A USER ISN'T LOGGED IN, THEN REDIRECT THEM SOMEWHERE
res.redirect('/');
}
As I wanted ALL routes (except for login routes off course) to pass authorization, I solved it as follows:
var ensureAuthenticated = function(req, res, next) {
if (req.isAuthenticated()) return next();
else res.redirect('/login')
}
// usersRouter contains all open routes like '/login':
app.use('/', usersRouter);
// From here on, all routes need authorization:
app.use(ensureAuthenticated);
app.use('/', indexRouter);
app.use('/api/foo', fooRouter);
app.use('/api/bar', barRouter);
I'm not sure what do you mean by "but nowhere in that document can I find how to authorise my users". Passportjs won't authorize any user. It is an authentication middleware. Authorization is different from authentication.
I think you are looking for application level middleware. You have to use app.use to make authentication work for each request to the server.
You can read more about it here. https://expressjs.com/en/guide/using-middleware.html#middleware.application
I am setting up a nodejs project with passportjs and passport-jwt. I see where you can specify passport.authenticate for each route you want to secure. However, I do not see a way to lock down all router except maybe login and register. I see where express-jwt allows for the use of express-unless, which seems to accomplish this functionality. Is there a similar mechanism for passport-jwt and if so how would this be accomplished?
Actually you don't even need express-unless you can use the fact that express allow to register middlewares that get executed all the time to do your filtering
const express = require('express');
const app = express();
function authenticateSomeRoutesMiddleware(req, res, next) {
if (/(login|register)/.test(req.originalUrl)) {
// No authentication needed
return next();
} else {
// Option 1 => use default passport logic
// which respond with a 401 unauthorized status if authentication fails
passport.authenticate('jwt', { session: false}), function(req, res, next) {
// Do something now you know that the user has been authenticated
return next(); // this will call the next middleware on the stack
})(req, res, next);
// Option 2: use a custom callback to allow your application
// to handle success or failure
// As per passport spec:
// - If authentication failed, user will be set to false.
// - If an exception occurred, err will be set.
// - An optional info argument will be passed, containing additional details
// provided by the strategy's verify callback.
passport.authenticate('local', function(err, user, info) {
if (err) {
// Error in authentication process; handle it or call...
return next(err);
}
if (!user) {
// Authentication failed (based on your strategy's implementation)
// You can for example try again
return res.redirect('/login');
}
// If you are using session to store the user call req.logIn() else call `return next()` directly
req.logIn(user, function(err) {
if (err) { return next(err); }
return next();
});
})(req, res, next);
}
}
// add this BEFORE your route definitions
app.use(authenticateSomeRoutesMiddleware);
// add all your routes here
app.use('/login', function(req, res, next) {
// do something
});
app.use('/register', function(req, res, next) {
// do something else
});
app.use('/some/protected/route', function(req, res, next) {
// this will get called once the authentication process has been cleared
});
//...
Currently using node.js, express & passport.js to create a custom website/application.
Having followed several guides, I have a functioning login/logout system with authentication. However, should a user revisit and their session is still active, it doesn't redirect them to the 'dashboard'.
Current root route:
/* GET login page. */
router.get('/',function(req, res) {
// Display the Login page with any flash message, if any
res.render('index', { message: req.flash('message') });
});
I am making use of the isAuthenticated function, as below:
var isAuthenticated = function (req, res, next) {
if (req.isAuthenticated())
return next();
res.redirect('/');
}
How do I get it to automatically redirect users with an existing session? Any pointers most welcome!
Ok, I figured it out. In the / route, I queried whether req.user was set.
/* GET login page. */
router.get('/',function(req, res) {
if(req.user){
res.redirect("/dashboard");
}else{
// Display the Login page with any flash message, if any
res.render('index', { message: req.flash('message') });
}
});
You can attach a middleware with "/" endpoint something like this.
router.get('/', sessionValidate, function(req, res, next) {
res.render('login');
});
Where sessionValidate looks something like this :
function sessionValidate(req,res,next){
console.log(req.user,"i am here");
users.findById(req.user,function(err, user) {
if(user!=null){
req.session.user = user;
res.locals.user=user;
res.redirect("/home")
}
else {
next();
}
});
}
I am building an app using Express/Node.js with Passport.js(passport-local) & Mongoose.
There are two kind of users:
regular users (they login using /user-login page and passport strategy 'local-user-login'; regular users are stored in "Users" MongoDB collection)
admins (they login using /admin-login page and passport strategy 'local-admin-login'; admins are stored in "Admins" MongoDB collection)
I also have 2 pages: /user_home (needs to be accessible to logged regular users only) and /admin_home (for logged admins only)
Route for /user_home:
app.get('/user_home', isLoggedIn, function(req, res) {
// render the page
});
function isLoggedIn(req, res, next) {
if (req.isAuthenticated())
return next();
res.redirect('/login');
}
If I log in as an admin and try to access /user_home, it doesn't allow me, which is fine. My question is: how can I define another "isLoggedIn" function that checks if I am logged in as an admin rather than a regular user? Ideally I would like to have a function "isLoggedInAsUser" and another one "isLoggedInAsAdmin".
So far I tried defining the /admin_home route the same way:
app.get('/admin_home', isLoggedIn, function(req, res) {
// render the page
});
But it's obvious why it doesn't work. The code doesn't know that I want it to check if it's an admin rather than a regular user.
Passport stores authenticated user in req.user. So you can write middleware functions like this:
function allowAdmins(req, res, next) {
if (req.user.role === 'Admin') return next();
res.redirect('/user-login');
}
function allowRegular(req, res, next) {
if (req.user.role === 'Regular') return next();
res.redirect('/admin-login');
}
And then in routes:
var userRouter = express.Router();
userRouter.use(isLoggedIn);
// Only authenticated users are allowed
userRouter.get('/home', isRegular, function (req, res) {});
userRouter.get('/admin', isAdmin, function (req, res) {});
app.use('/user', userRouter);
in session object store role information
in the route configuration level, write middleware like
var adminRoutes = express.routes();
adminRoutes.route('/admin/*', function (req, res,next)
{
if(req.session.role==='Admin')
return next();
else
{
res.send("Authorization Error")
}
}
app.use(adminRoutes);
same for user routes