How to secure a namespace with passport js? - javascript

Assume I have a route with the following namespace:
app.use('/logged', adminRoute);
Now, I have created the following passportjs function:
app.get('/logged/panel', function (req, res) {
if (req.user === undefined) {
res.redirect('/login');
} else {
res.render('/logged/panel', {
user: req.user
})
}
});
This function checks wether the user is authenticated on the /logged/panel pattern.
I want to modify this function so it will perform checks on each get/post url pattern from adminRoute. How can I do this correctly?

Consider using express.Router.
function ensureAuthenticated(req, res, next) {
if(logged) return next();
res.redirect('/login');
}
var loggedRouter = express.Router();
loggedRouter
.use(ensureAuthenticated)
.get('/panel', panelHandler)
.get('/other', otherHandler);
var mainRouter = express.Router();
mainRouter.use('/logged', loggedRouter);
app.use(mainRouter);
You can include checking if user is logged inside ensureAuthenticated function. This middleware function will always be executed before /logged/panel and /logged/other.

Related

Checking whether user is logged in passport.js

I use passport.js to authenticate user. I have 2 function there to check whether user is logged in or not.
First function:
isLoggedIn(req, res, next) {
if (req.isAuthenticated()) {
return next();
}
else {
res.redirect('/');
}
}
2nd function:
isLoggedInCheck(req, res) {
if (req.isAuthenticated()) {
return true;
}
else {
return false;
}
}
I take these 2 functions in class called Helper.
When I use the 1st function (I pass it in routes function as middleware) it works:
var Helper = require('../helpers/helper');
var helper = new Helper();
router.get('/', helper.isLoggedIn, admin.melihat_daftar_venue);
But when i want to use second function:
if (helper.isLoggedInCheck) {
//code
}
else{
}
The function just return function definition instead of true/false. How to fix it. Thanks
You are using isLoggedIn as a ExpressJS middleware while isLoggedInCheck inside condition that's why you need to call function( helper.isLoggedInCheck(req, res) inside if condition while define inside get function
if (helper.isLoggedInCheck(req, res)) {
//code
}
else{
}
and first one is
router.get('/', helper.isLoggedIn, admin.melihat_daftar_venue);
or (not recommended, just showing example)
router.get('/', (req, res, next) => {
helper.isLoggedIn(req, res, next)
}, admin.melihat_daftar_venue);

Why is req.somevariable and res.locals not working with jwt callbacks?

We have a route & a middleware like this:
When we do them like this:
//middleware
router.use((req, res, next) => {
// check header or url parameters or post parameters for token
let token = req.body.token || req.query.token || req.headers['x-access-token'],
// verifies secret and checks exp
jwt.verify(token, config.secret, (err, decoded) => {
if (err) {
return res.json({
success: false,
message: 'Failed to authenticate token.'
});
} else {
// if everything is good, save to request for use in other routes
res.locals.test = "test";
req.somevariable = "variable1";
console.log("res.locals.test inside middleware ", JSON.stringify(res.locals.test));
console.log("req.somevariable inside middleware ", JSON.stringify(req.somevariable));
next();
}
});
next();
});
//TestRoute
router.get('/TestRoute', (req, res) => {
console.log("res.locals.test outside middleware ", JSON.stringify(res.locals.test));
console.log("req.somevariable outside middleware ", JSON.stringify(req.somevariable));
});
The values of req.somevariable and res.locals.test are undefined outside middleware
When we do them like this:
//middleware
router.use((req, res, next) => {
res.locals.test = "test";
req.somevariable = "variable1";
console.log("res.locals.test inside middleware ", JSON.stringify(res.locals.test));
console.log("req.somevariable inside middleware ", JSON.stringify(req.somevariable));
next();
});
//TestRoute
router.get('/TestRoute', (req, res) => {
console.log("res.locals.test outside middleware ", JSON.stringify(res.locals.test));
console.log("req.somevariable outside middleware ", JSON.stringify(req.somevariable));
});
The values of req.somevariable and res.locals.test are available outside middleware.
What is the problem here?
res.locals.VARIABLENAME = req.user
VARIABLENAME (whatever variable you set it to) can show up as undefined when you use .ejs or when dynamic rendering with that variable, you can get errors like your variable name is undefined.
THIS IS AN ODDITY with res.locals: when you want to use the variable name you set to res.locals with rendering, you have to define req.user in your function THAT RENDERS THE FILE!
Backend: res.locals.currentUser = req.user
//THIS FUNCTION WILL RENDER PERFECTLY LETTING ME USE currentUser in my .ejs file
upgradeForm(req, res, next) {
let saved = req.user;
if(req.user){
res.render("users/upgrade");
} else{
req.flash("notice", "You've successfully signed in!");
res.redirect("/");
}
}
HOWEVER
//THIS FUNCTION WILL SAY currentUser is UNDEFINED IN MY .ejs file
upgradeForm(req, res, next) {
if(req.user){
res.render("users/upgrade");
} else{
req.flash("notice", "You've successfully signed in!");
res.redirect("/");
}
}
No code difference except for that the working function rendering has req.user set to a variable (you don't even have to use that variable). Took me 9 hours to solve this problem but now you know!

Passport JWT req.user is undefined in one of my routes

I'm having an absolute nightmare trying to set up JWT with my express app! Think I've got it mostly working now, I have a register route and login route that both work correctly and generate valid tokens and I have another route in my '/users' route that I test the authentication with and this is all fine. But I have another file containing routes for '/api' which is where the authentication is actually important and I have a similar test route that tries to access req.user (just like I do in my other route) but it seems like req.user is undefined. Through some debugging it looks like the user is in req.account which is very odd and I don't understand why its not in req.user
I define my jwt strategy in /config/passport.js
'use strict';
const User = require('../models/user'),
config = require('./main'),
JwtStrategy = require('passport-jwt').Strategy,
ExtractJwt = require('passport-jwt').ExtractJwt;
//exported to be used by passport in server set up
module.exports = function (passport) {
const jwtOptions = {
// Telling Passport to check authorization headers for JWT
jwtFromRequest: ExtractJwt.fromAuthHeader(),
// Telling Passport where to find the secret
secretOrKey: config.secret
};
const jwtLogin = new JwtStrategy(jwtOptions, function(payload, done) {
User.findById(payload._id, function(err, user) {
if (err) { return done(err, false); }
if (user) {
done(null, user);
} else {
done(null, false);
}
});
});
passport.use(jwtLogin);
}
passport is passed as an argument to this and then initialised in the main express file
here is the /users route file, this works fine. sending a GET request to /users/isAuth with Authorization header and 'JWT ' works fine and I get my username sent back to me
"use strict";
const express = require('express'),
router = express.Router(),
jwt = require('jsonwebtoken'),
User = require('../models/user'),
config = require('../config/main'),
passport = require ('passport');
function generateToken(user) {
return jwt.sign({_id: user._id}, config.secret, {
expiresIn: 10080
});
}
.
. Here are routes for login and register they perform as expected
. and work fine
.
/* ==================================
Test Authentication Route
================================== */
router.get('/isAuth', passport.authenticate('jwt', { session: false }), function(req, res) {
console.log(req.user);
res.json({username: req.user.username});
});
module.exports = router;
In this file though, for the api routes sending a request to GET /api/testAuth exactly the same as before with the same token and the same headers I get back no req.user and in the console I see that req.user is undefined. But in the console there does seem to be the user object just as req.account? I don't understand what is happening here hopefully someone can help!
"use strict";
const express = require('express'),
router = express.Router(),
jwt = require('jsonwebtoken'),
Server = require('../models/server'),
passport = require('passport');
// Test route to see if logged in user is matt
router.get('/testAuth', passport.authorize('jwt', { session: false }), function(req, res) {
console.log(req.user);
if (req.user) {
if(req.user.username == "matt") {
res.send("You are matt!");
} else {
res.send("You are not matt!");
}
} else {
res.send("no req.user");
}
})
module.exports = router;
req.user object is only set when you use a passport authentication strategy that uses sessions. In this case, the authentication is stateless since you have specified {session: false}, which is how it should be for an api. Thus, the session does not have a user object. Here is how I set my req.user object in the passport.authenticate middleware:
Modify your jwtOptions to enable passing the req object to JwtStrategy function:
const jwtOptions = {
// Telling Passport to check authorization headers for JWT
jwtFromRequest: ExtractJwt.fromAuthHeader(),
// Telling Passport where to find the secret
secretOrKey: config.secret,
passReqToCallback: true, //<= Important, so that the verify function can accept the req param ie verify(req,payload,done)
};
Modify the parameters to your JwtStrategy to include the request object as the first parameter; then within the if (user) block, just assign the returned user object to req.user:
const jwtLogin = new JwtStrategy(jwtOptions, function(req, payload, done) {
User.findById(payload._id, function(err, user) {
if (err) { return done(err, false); }
if (user) {
req.user = user; // <= Add this line
done(null, user);
} else {
done(null, false);
}
});
});
That is it: now any route that has the passport.authenticate("jwt", {session: false}) middleware will receive req.user upon successful authentication.
You are using passport.authorize in your testAuth route, this is for users that are already logged in and have session information. Since you are not using session storage you do not have a persistent req.user object and so should use passport.authenticate on all routes
http://passportjs.org/docs/authorize

Securing a specific route node.js

Hey I'm using basic auth for Node.JS to secure a route. I'm pretty new to Node.JS and don't understand what the next function does in this case. What I'm trying to do is to secure a the route: /admin/
Note: This is a project for learning purposes so the login part is not too serious and won't be used live.
authentication.js
var basicAuth = require('basic-auth');
exports.BasicAuthentication = function(request, response, next) {
function unauthorized(response) {
response.set('WWW-Authenticate', 'Basic realm=Authorization Required');
return response.send(401);
};
var user = basicAuth(request);
if (!user || !user.name || !user.pass) {
return unauthorized(response);
};
if (user.name === 'name' && user.pass === 'pass') {
return next();
} else {
return unauthorized(response);
};
};
and app.js where I imported the module authentication:
app.get('/admin/', authentication.BasicAuthentication, function(req, res){
console.log("hi u need to login");
});
So what I want to do is to route the user further if the authentication goes through.
Thanks in advance!
Try:
app.get('/admin/', authentication.BasicAuthentication);
app.get('/admin/', function(req, res) {});
This function is known as a middleware:
var basicAuth = require('basic-auth');
exports.BasicAuthentication = function(request, response, next) {
function unauthorized(response) {
response.set('WWW-Authenticate', 'Basic realm=Authorization Required');
return response.send(401);
};
var user = basicAuth(request);
if (!user || !user.name || !user.pass) {
return unauthorized(response);
};
if (user.name === 'name' && user.pass === 'pass') {
return next();
} else {
return unauthorized(response);
};
};
middleware is a function that you can define for various purposes:
using middleware
writing a middleware
In a simple way is a function that runs before performing another action, one general purpose is to protect certain routes for unauthorized access.
You can protect private routes calling then authentication.BasicAuthentication before function(req, res) {}
Some example:
app.get('/user-profile/', authentication.BasicAuthentication, function(req, res){
//private info
});
app.get('/foo/', function(req, res){
//public info
});

How to create a reusable function in Node without writing boilerplate code

I am using Express.js as http server. Defined all my routes.
Most endpoints need to verify session before returning a response. E.g. below code serves users in the system and list of services respectively:
function getUsers(req, res, next) {
verifyUser(req, res, next, function () {
//serve users
});
}
function getServices(req, res, next) {
verifyUser(req, res, next, function () {
//serve services
});
}
You probably noticed there is a verifyUser function which validates the session. Which is as below.
function verifyUser(req, res, next, callback) {
var sessionKey = req.cookies.sessionKey;
var user = users.userBySession(sessionKey);
if (user) {
callback(req, res, next, user);
} else {
res.status(401).send({
message: 'Unauthorized'
});
}
}
As you can see I keep passing in req, res and next parameters along with a callback whenever I use this function.
I tried to use apply function to make it easier. Changed my getUsers function like this:
function getUsers(req, res, next) {
verifyUser
.apply(null, arguments, function () {
//serve users
});
}
The problem with this approach is callback is not passed into verifyUser function. And I don't really like passing null as scope with each call.
How can I achieve this by writing less and better code ? Any ideas?
You could use bind to create a 'partial function':
// create bound responseHelper object
var responseHelper = verifyUser.bind(null, req, res, next);
// usage
responseHelper(getUsersCallback); // same as verifyUser(req, res, next, getusersCallBack);
I think you're looking to turn verifyUser into a middleware function.
function verifyUser (req, res, next) {
var user = // yadda yadda session stuff
if (user) {
req.user = user; // [1] what you do to the req object here...
} else {
return res.status(401).send({ message: "No way Smokey Joe"});
/**
* alternatively, do something like
* var err = new Error("Not authorized");
* err.statusCode = 401;
* return next(err);
*
* this will kick off Express' error handling mechanism,
* which you should read about in the docs (see the link below)
*/
}
next();
// very important to call next after this verifyUser has done its job
// if you don't, the next middleware won't go off,
// and the request will just hang
}
function getUsers (req, res, next) {
// [2] will show up on the req object here, assuming you chain these
// two functions together as middleware
}
app.get("/users", verifyUser, getUsers);
app.get("/services", verifyUser, getServices);
// here's a route that needs no session auth, so no need to verifyUser
app.get("/latest-posts", getLatestPosts);
When you tell Express to use a function or attach a function to a route path via get('/my/route', hanlderFun) or some such, you've basically turned handlerFun into a middleware.
You can define however many middleware as handlers on a route as you like, and they'll all execute in turn as long as you keep calling next.
app.post("/checkout", verifyUser, tallyCart, checkInventory, doPayment, sendInvoice);
The job of next is to pass control from the current middelware to the next one. It's an object
You can do other stuff with next, too, which you should read up on in the docs.
http://expressjs.com/en/guide/writing-middleware.html
http://expressjs.com/en/guide/using-middleware.html
The docs on routing have good info on middleware as well:
http://expressjs.com/en/guide/routing.html
For extra credit, check out error handling middleware, too:
http://expressjs.com/en/guide/error-handling.html

Categories

Resources