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);
}
});
Related
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");
});
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...
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
}
}
I would like to pass a certain permission into the authenticated call on routes in Passport.js.
This is what I have now:
app.get('/mypage', app.authenticated, function (req, res, next) {
if (!req.user.hasPermission('myPermission')) {
return res.redirect('/unauthorized');
}
// do stuff
};
var middleware = function(app) {
app.authenticated = function (req, res, next) {
if (req.isAuthenticated()) {
return next();
}
if (req.method == 'GET') {
req.session.returnTo = req.originalUrl;
}
res.redirect('/login');
};
}
module.exports = middleware;
I would instead like to pass the permission into authenticated like this:
app.get('/mypage', app.authenticated('myPermission'), function (req, res, next) {
// do stuff
};
But as far as I can tell, since authenticated gets the parameters it needs automatically, I can't just add a new one.
How can I go about doing this?
You can access req.body values in any of the express middleware.
In your app.authenticated(..) middleware, prior to execution set the value :
req.body['permission'] = 'myPermission'
Use the value of req.body['permission'] for authorisation.
I'm setting up dynamic routes and using basicAuth (when a user/pass has been configured). Here's what I have:
var basicAuth = express.basicAuth,
auth = function(req, res, next) {
if (config.hasOwnProperty(req.params.project)) {
var auth = config[req.params.project].auth;
if (auth) {
basicAuth(function(user, pass, callback) {
// Check credentials
callback(null, user === auth.user && pass === auth.pass);
})(req, res, next);
} else {
// No authentication
return true;
}
}
};
Then, my route looks like this:
app.get("/:project", auth, function (req, res) {
...
});
It's getting the config from a file which either contains the auth object with auth.user and auth.pass or is set to false. When set to false I'd like to (obviously) skip authentication.
The basicAuth is working when turned on, but I can't figure out how to dynamically bypass it.
Connect doesn't check the return value of the middleware, so returning true doesn't mean anything. You need to call the next function so that Connect knows to continue.
var basicAuth = express.basicAuth,
auth = function(req, res, next) {
if (config.hasOwnProperty(req.params.project)) {
var auth = config[req.params.project].auth;
if (auth) {
basicAuth(function(user, pass, callback) {
// Check credentials
callback(null, user === auth.user && pass === auth.pass);
})(req, res, next);
} else {
// No authentication
next();
}
}
};
Also, it looks like the basicAuth callback can be synchronous, so it's probably cleaner to do this:
basicAuth(function(user, pass) {
// Check credentials
return user === auth.user && pass === auth.pass;
})(req, res, next);
Finally, basicAuth has another alternate form, so you can just do:
basicAuth(auth.user, auth.pass)(req, res, next);