Multiple authentication controllers on one route - node.js

I am trying to add two authentication controllers to one route. For example, this is basically what I am trying to make:
router.route('/employees')
.get(authController1.isAuthenticated, myController1.get1)
.get(authController2.isAuthenticated, myController2.get2);
The isAuthenticated function is as follows:
exports.isAuthenticated = passport.authenticate('basic', {
session: false
});
Does anyone know how this would be possible?
Thanks,
Daniel

Route:
router.route('/employees')
.get(authController.isAuthenticated1, authController.isAuthenticated2, myController1.get1)
authController :
exports.isAuthenticated = function(req, res, next) {
// Authentication code
if (!req.isAuthenticated) {
// Not authenticated
return res.status(401).send({
message: 'User is not authenticated'
});
}
next();
};
exports.isAuthenticated2 = function(req, res, next) {
// Authentication2 code
if (!req.isAuthenticated2) {
// Not authenticated
return res.status(401).send({
message: 'User is not authenticated'
});
}
next();
};
myController
exports.get1 = function(req, res) {
// Both are authenticated so we can proceed.
}

Perhaps something like this?
exports.isAuthenticated = function(req, res, next) {
req.user == 'type1' ? fnType1(req, res, next) : fnType2(req, res, next); // Do check and call method.
};
function fnType1(req, res, next) {
//Authentication code
// Attach type to req
req.userType = 1;
next();
}
function fnType2(req, res, next) {
//Authentication code
// Attach type to req
req.userType = 2;
next();
}
exports.get1 = function(req, res) {
// Both are authenticated so we can proceed.
if(req.userType = 1){
// Do something
} else {
// Do something else
}
}

Related

Exposing user object inside the req object

I am trying to get user object inside the req, so I can have it on all my routes. This is my setup:
app.js:
// Use the passport middleware
app.use(passport.initialize());
// load passport strategies
const localSignupStrategy = require('./server/passport/local-signup');
const localLoginStrategy = require('./server/passport/local-login');
passport.use('local-signup', localSignupStrategy);
passport.use('local-login', localLoginStrategy);
// View engine setup
app.set('views', path.join(__dirname, '/server/views'));
app.set('view engine', 'pug');
// Serve static assets normally
app.use(express.static(path.join(__dirname, '/dist')));
// Define routes
app.use('/auth', auth); //Auth controller
app.use('/api', api);
Route for Auth controller:
const express = require('express');
const router = express.Router();
const authController = require('../main/controllers/authController');
// POST /auth/signup
router.post('/signup', authController.postSignup);
// POST /auth/login
router.post('/login', authController.postLogin);
module.exports = router;
authController.postLogin
exports.postLogin = function(req, res, next) {
const validationResult = validateLoginForm(req.body);
if (!validationResult.success) {
return res.status(400).json({
success: false,
message: validationResult.message,
errors: validationResult.errors
});
}
return passport.authenticate('local-login', (err, token, userData) => {
if (err) {
if (err.name === 'IncorrectCredentialsError') {
return res.status(400).json({
success: false,
message: err.message
});
}
return res.status(400).json({
success: false,
message: 'Could not process the form.'
});
}
return res.json({
success: true,
message: 'Login success.',
token,
user: userData
});
})(req, res, next);
};
This is my normal controller route:
// GET /api/cms
router.get('/cms/', authCheck(), getCmsDataController.getCmsData);
module.exports = router;
authcheck.js
module.exports = function(roles) {
// Return middleware
return (req, res, next) => {
if (!req.headers.authorization) {
return res.status(401).end();
}
// Get the last part from a authorization header string like "bearer token-value"
const token = req.headers.authorization.split(' ')[1];
// Decode the token using a secret key-phrase
return jwt.verify(token, config.jwtSecret, (err, decoded) => {
// 401 not unauthorized
if (err) return res.status(401).end();
const userId = decoded.sub;
// Check if user exists
return User.findById(userId, (err2, user) => {
if (err2 || !user) return res.status(401).end();
req.currentLoggedUser = user;
console.log(user.role);
if (roles) {
if (roles.indexOf(user.role) > -1) return next();
else return res.status(401).end();
}
return next();
});
});
};
};
And the controller itself:
// GET /api/cms-data/
exports.getCmsData = function(req, res, next) {
return res.json({
message: 'Lets see does this thing work or not!!!'
});
};
Issue is when I reach the getCmsData controller, I would like to have a user object inside the req object. My user has some properties like role and gender, which I need access to. I have one hacky solution, but I think there is a way to do that.
Could you create a middleware function for this purpose:
function getRequestUser(req) {
// In reality you'd load from data store based on request.
return {id: 1, name: "Jim Smith"};
}
function addUserMiddleWare(req, res, next) {
req.user = getRequestUser(req);
next();
}
// Then add it to your route.
// GET /api/cms
router.get('/cms/', authCheck(), addUserMiddleWare, getCmsDataController.getCmsData);
module.exports = router;
// Or, apply to all paths on router
router.use(addUserMiddleWare);

Second middleware is only called after the route method

I have 2 middleware , one that check if the user has a valid token and the second one that check if the user has permissions. The probleme is that after calling the first middleware the program is going directly inside my route method instead of calling the 2nd middleware. Here my code :
app.use(function(req, res, next) {
checkToken(req, res, next);
checkPermission(req, res, next);
});
app.post("/test", (req, res) => {
console.log("route");
})
function checkToken(req, res, next){
console.log("check token");
if(validToken())
next();
else
res.send("no valid token");
}
function checkPermission(req, res, next){
console.log("check permission");
if(permission())
next();
else
res.send("no permission");
}
Output I get:
check token -> route -> check permission
Output that I expect :
check token -> check permission -> route
What I want my program to do is to check either if the user has a valid token and if he has permission before going inside my route method!
Is this the right way to do it ?
app.use(checkToken);
app.use(checkPermission);
app.post("/test", (req, res) => {
console.log("route");
});
...
Each express middleware is given one next callback to trigger the next middleware, but here you are calling two functions inside the middleware which calls next in each method. You have to refactor your code like this,
app.use(checkToken); // <== first middleware
app.use(checkPermission) // <== Second middleware
app.post("/test", (req, res) => {
console.log("route");
})
function checkToken(req, res, next) {
console.log("check token");
if (validToken())
next();
else
res.send("no valid token");
}
function checkPermission(req, res, next) {
console.log("check permission");
if (permission())
next();
else
res.send("no permission");
}
See also Writing middleware for use in Express apps for a better understanding how middleware work.
/* Check token */
function checkToken(req, res, next) {
console.log("check token");
if(validToken())
next();
else
res.send("no valid token");
}
/* Check permission */
function checkPermission(req, res, next) {
console.log("check permission");
if(permission())
next();
else
res.send("no permission");
}
/* Calling the middleware in right order */
app.use(checkToken, checkPermission, (req, res, next) => {
next();
});
/* Finally our route */
app.post("/test", (req, res) => {
console.log("route");
});

nodeJs, Express get response and call another function

I have post.route.js where I mention
var post = require('../controllers/post.controller');
router.route('/posts').get(post.getPosts, post.setCache);
and my post.controller.js has the
exports.getPosts = function(req, res, next) {
var qstring = postQueryString;
getPostsDataByQuery(qstring,req,res,next);
}
function getPostsDataByQuery(queryString,req, res, next){
logger.info('start',req.route.path);
// some code here
return res.json(rows);
next();
};
exports.setCache = function(req, res, next){
console.log('here in set function');
cache.setExp(req, rows);
return true;
}
if in the setExp I log the not showing me
exports.setExp = function(req, data){
console.log('here');
}
You could make use of the next method:
function getPosts(queryString, req, res, next){
// your code
next();
};
function setCache(req, res) {
cache.setExp(req.originalUrl, process.env.CACHE_POST_EXP_TIME, rows);
return true;
}
router.route('/posts').get(post.getPosts, post.setCache);

Use Passport Local & JWT Strategy on same app (on same route)

so my route (for '/dash') looks like this:
// validating using JWT
router.post('/dash', passport.authenticate('jwt', {session: false}), function (req, res) {
res.json({'success': true});
});
// validating using LOCAL
router.post('/dash', authenticationHelpers.isAuth, function (req, res) {
res.json({'success': true});
});
// authenticationHelpers.isAuth
function isAuth(req, res, next) {
if (req.isAuthenticated())
return next();
res.status(401).json({"authenticated": false});
}
So, how do I use both Local & JWT Strategy on same app (on same route) ? How do I combine them both.
Note: Local for web app, JWT for mobile app
Finally figured it out.
Modified isAuth function:
function isAuth(req, res, next) {
if (req.headers.authorization) {
passport.authenticate('jwt', {session: false}, function (err, user, info) {
if ((!err || !info) && user) {
req.user = user;
return next();
}
res.status(401).json({authenticated: false, message: "Login expired."});
})(req, res, next);
} else {
if (req.isAuthenticated())
return next();
res.status(401).json({authenticated: false});
}
}
Suggestions are welcomed...

How to call Connect middleware directly?

I have a express route like this:
app.get('/', auth.authOrDie, function(req, res) {
res.send();
});
where authOrDie function is defined like that (in my auth.js module):
exports.authOrDie = function(req, res, next) {
if (req.isAuthenticated()) {
return next();
} else {
res.send(403);
}
});
Now, when the user is not authenticated, I would like to verify if the http request has a Authorization (Basic) header. To do that, I would like to use the great connect middleware basicAuth().
As you know, Express is built on top of Connect, so I can use express.basicAuth.
The basicAuth is generally used like that:
app.get('/', express.basicAuth(function(username, password) {
// username && password verification...
}), function(req, res) {
res.send();
});
But, I would like to use it in my authOrDie function like that:
exports.authOrDie = function(req, res, next) {
if (req.isAuthenticated()) {
return next();
} else if {
// express.basicAuth ??? ******
} else {
res.send(403);
}
});
****** How can I call the basicAuth function with the good parameters (req ? res ? next ? ...).
Thanks.
Calling the express.basicAuth function returns the middleware function to call, so you'd invoke it directly like this:
exports.authOrDie = function(req, res, next) {
if (req.isAuthenticated()) {
return next();
} else {
return express.basicAuth(function(username, password) {
// username && password verification...
})(req, res, next);
}
});

Resources