How to check Passport isAuthenticated on express.Router() - node.js

Using passport.js, what is the recommended way to check if a user isAuthenticated?
I see examples of people doing things like this:
app.get('/', isAuthenticated, function(req,res){});
How does this even work, app.get only accepts two arguments?
What about when I use express.Router()?
What's the correct syntax for router.get?
More generally, checking isAuthenticated at every route seems inefficient. Is there a better way to check authentication in an Express app?
Thanks.

app.get accepts as many middlewares as you need. According to the documentation:
router.METHOD(path, [callback, ...] callback)
...
You can provide multiple callbacks, and all are treated equally, and behave just like middleware, except that these callbacks may
invoke next('route') to bypass the remaining route callback(s). You
can use this mechanism to perform pre-conditions on a route then pass
control to subsequent routes when there is no reason to proceed with
the route matched.
This is how your authentication middlware function may look like:
function isAuthenticated(req, res, next) {
if(/*check authentification*/) {
return next();
}
res.send('auth failed');
}
On the other hand passport.js provides a built-in function that can be used as Express middleware.
app.post('/login',
passport.authenticate('local'),
function(req, res) {
// If this function gets called, authentication was successful.
// `req.user` contains the authenticated user.
res.redirect('/users/' + req.user.username);
});
Authenticating requests is as simple as calling passport.authenticate() and specifying which strategy to employ. Strategies must be configured prior to using them in a route. Continue reading the chapter on configuration for details.

Related

router.param not triggering passport.js initialize in app.use

I've got a fairly straight forward Node Express routing app set up, to which I've just added passport.js authentication. I'm now trying to integrate this with the existing routes.
I run the basic middleware of:
app.use(passport.initialize());
app.use(passport.session());
and then if I run a simple
app.get('/route', (req, res)=>{
console.log(req.user)
});
I get the expected result of it printing the logged in user. So far so good...
However, I'm now trying to access this req.user within some of the child routes that I have set up. In the first route I'm trying the first step is to bring in a parameter and compare it against the req.user:
app.use('/route/:userId', idRouter);
And then:
idRouter.param("userId", async (req, res, next, userId) => {
console.log(userId)
console.log(req.user.id)
})
This route fires and prints out the parameter, but req.user is undefined. I can't see a reason why this is the case.
To help debug this I've put some logging in the deserialize function and I can see that it's not being called when I hit the idRouter. I can't see why this would be the case given it's inside an app.use function which should be called every time.
Help please!
I solved this in the end, it was an issue with CORS. Just needed to include credentials in API calls.

NodeJs/Express: Authorise all endpoints except one

In my NodeJs/express based application, I am authorizing calls to all the endpoints by using the following middleware.
app.use(restrictByCookieMiddleware);
I want to authorize all endpoints except one i.e. I don't want "restrictByCookieMiddleware" middleware to run for "/metrics" endpoint. Is there a way to escape one endpoint?
Here, I found some examples that matches endpoint for which middleware should run, I am looking for a solution that skips one.
Your have a couple of choices:
First, you can just define the one exception route handler BEFORE the middleware. Then, it will handle that route and the routing will never get to the middleware.
app.get("/login", (req, res) => {
// handle that one special route here
});
// all other routes will get this middleware
app.use(restrictByCookieMiddleware);
Second, you can make a wrapper for the middleware that compares to the one specific route and skips the middleware if it's that route:
app.use((req, res, next) => {
// shortcircuit the /login path so it doesn't call the middleware
if (req.path === "/login") {
next();
} else {
restrictByCookieMiddleware(req, res, next);
}
});
// then, somewhere else in your code would be the /login route
app.get("/login", ...);
Third, if you have multiple routes that you want to skip the middleware for, you can segment things by router. Create a router for the non-middleware routes and put all of them on that router. Hook that router into the app object first.
Then, create a second router that contains the middleware and has all your other routes on it.
Place that specific route, you want to exclude, before this line:
app.use(restrictByCookieMiddleware);
So this will solve your problem.

nodejs express wildcard route not working

I'm doing an API in nodejs with express as router.
Now i'm trying to implement an client-id and an apikey to add some security to the API, and the problem that i'm facing is the next:
One of my API call is like this:
router.get("roles/get-objects/:mail/:filter*?")
So this means, that i can request an object like this:
/roles/get-objects/mail#mail.com/customer
Now the tricky part begins... when I needed to stablish a middleware to read an client-id and an apikey to verify that the client is authorized to se the API, so I did this:
In the declaration of the middleware, I use this wildcard:
router.all('/*', function (req, res, next) {
XXXX})
The thing is, I have tried in the middleware, as a wildcard everything...
I want that any API call is filtered thru that middleware, but apparently I can't find the right wildcard for it...
When I use /roles/* as wildcard, if I do a request to /roles it does work, but when I use the complete URL like: /roles/get-objects/mail#mail.com/customer it doesn't go thru my middleware.
So anybody has any idea? i'm starting to loose my mind
Thank you so much to all of you!
EDIT:
Now i'm using this middleware declaration:
router.use(function (req, res, next) {XXXX})
So when I call:
/roles/get-objects/
It's executed, the problem is when I add the email to the route:
/roles/get-objects/mail#mail.com
The app goes directly to the route that i have for that, but omits my middleware:
router.get("roles/get-objects/:mail",
I don't understand why is this happening, apparently everything should go thru my middleware first, or am I wrong?
If you want to establish a middleware to check all HTTP request whose URL starting with /roles/, the middleware should be placed before any other specific router definition:
router.use('/roles', function(req, res, next) {...});
...
router.get('/roles/get-objects/:mail', ...);
If the middleware is defined after specific route, when HTTP request comes in, the specific route is targeted and processed, the middleware won't be executed any more:
router.get('/roles/get-objects/:mail', ...);
...
router.use('/roles', function(req, res, next) {...}); // This middleware logic won't execute when request is sent to '/roles/get-objects/some-email', as the request has already been handled and response is already sent to browser.

Stop duplication of passportjs isAuthenticated code in Express route files

I am using passportjs for my authentication.
I have lots of different routes throughout the project, 95% of them require the following function:
// Middleware functions
function isAuthenticated(req, res, next) {
if (req.isAuthenticated())
return next();
res.redirect('/login');
}
At the moment, I am putting this function at the bottom of EVERY route file.
Is there a way to write it once, and be able to use it in all the route files?
If you add that middleware before the routes that require it, all requests will pass through it before they get forwarded to the correct route handler:
// doesn't require an authenticated request
app.use(router1);
// add the middleware just once
app.use(isAuthenticated);
// all following route(r)s require an authenticated request
app.use(router2);
app.use(router3);
...

ExpressJS middleware vs logic

What is the best way to structure the logic in an ExpressJS API.
So lets say I want to create a register and login function, and lets say I want a user to be logged in when he is successfully registered.
Now there are different ways I can achieve this, my question is then essentially: Which method is best and why?
METHOD 1
Everything is middleware:
router.post('/path', someMiddleware, register, login, function(req, res){
//You are registered and logged in.
});
So here both the register and login is treated as middleware, with both of them ending with a call to next(). This also results in the best reusability, because I can call either login and/or register again in any other express routing.
METHOD 2
Register is middleware and calls login (which is now just a standard function):
router.post('/path', someMiddleware, register, function(req, res){
//You are registered and logged in.
});
So here register is still middleware, but just before calling next() it calls login() which in this case is not middleware. The problem here is that if user that is already registered wants to login, should I create a hybrid login function that is also middleware and just call it in that specific post request?
METHOD 3
Logic is not in middleware and gets called in the wrapper:
router.post('/path', someMiddleware, funcWrapper(register, login), function(req, res){
//You are registered and logged in.
});
and then (in pseudo):
funcWrapper(actions...){
foreach actions
action()
}
Here logic and middleware are split, there is a wrapper that loops through all the functions that are passed in as parameter (in this case register and login)
Just a last question:
If I haven't asked enough questions, I have a last one. Is it better practice to end all express routing calls with
..., function(req, res){
//response
});
or with
..., lastMiddleware);
and then in the lastMiddleware there is some response

Resources