nodejs routing: all routes with authentication except first page - node.js

I am using passport for login.
I want to have all routes except '/' to require login.
I have a
ensureAuthenticated
function, which checks I am authenticated.
I'd rather not like to have to put into every route the middleware call:
app.get('/first', ensureAuthenticated,...)
app.get('/second', ensureAuthenticated,...)
Is there a way to assign ensureAuthenticated to all routes except '/'?

You can use app.all for that:
// regular route
app.get('/', ...);
// make sure all following routes will be passed through ensureAuthenticated
app.all('*', ensureAuthenticated);
app.get('/first', ...);
app.get('/second', ...);

Related

Express routes invoking multiple router function

I've created a NodeJS Express app. But my express route is invocking multiple routes function, one after another, but I only need one at a time.
My express app.js
app.use(routes)
Express router:
const router = express.Router();
router.post("/product", controller.productFunction)
router.post("/user", controller.userFunction)
router.get("/:id", idController.getId)
Whenever I create a post request for "/product" route, first the productFunction is invocked, but then the "/:id" routes getId function is also get invocked. Same thing happen for /user route as well. Always /:id route is getting invocked.
Is there any way to prevent this?
I even tried this way, but after the homepage loading then again it invockes getId function.
app.get("/", (req, res, next) => {
res.sendFile(..........);
});
app.use(routes);
I am sure that this is not an issue with the router itself.
You can't skip from POST to GET handling. So invocations are caused by different requests.
router.get("/:id", idController.getId) kind of wild card, and <server_url>/favicon.ico will trigger it
If you check it via browser it tries to get favicon or smth else and invokes this handler.
Try to make POST request via curl/Postman and idController.getId should not be called.
It is risky to serve static and process requests on a same level.
You can add some prefix to all your request, like that app.use('/api', routes); then static file will be available on /<file_name> and all server logic will be under /api/<request>

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);
...

How to check Passport isAuthenticated on express.Router()

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.

Resources