Restrict access to nodejs express routes - node.js

I have "internal" routes in my app :
app.get('/myroute', function(req, res) {
res.status(200).send('Hello!');
});
But the route is also accessible from outside:
curl http://example.com/myroute/?this=that
How to restrict the use of this route to the app / domain itself, ideally with a nice error?

As I see it, you have a few options:
Consider whether this route needs to be a web route at all, and not a function. If it's internal, surely a function would suffice?
Create a 'shared secret' for this function that must appear in either the header or as a request param. Then only callers that know this secret can call it.

Related

How can I share a root path using Express?

I want to be able to have two endpoints sharing the root path, both for different purposes.
One will be for obtain a user via its ID and the other via token.
Right now I have the following routes:
router.get('/:idUser', paramValidationRules(), validate, verifyJWT, getUserFromId);
router.route('/me').get(verifyJWT, getUserFromToken);
Running tests, the 'me' on the second route is considered a parameter and its redirected to the first route. Is possible to share a root path specifying that one will be used strictly to 'me' and the other one to an integer?
First, you're always hitting /:idUser before /me, so it will always stop at /:iduser and never react me.
So to solve the issue that you can never access /me, put the /me route declaration before /:idUser.
As to only catching numbers, there isn't a built in way, but you could use middleware (and change the order of your routes to the original):
router.get('/:idUser', function(req, res, next) {
req.id = /^\d+$/.test(req.params.idUser);
next();
}, paramValidationRules(), validate, verifyJWT, getUserFromId);
Then, (unfortunately) in all your middleware and handler (or just the handler) in the opening of the function add:
if(!req.id)
return next();

Is all communication from frontend to backend done via routes?

I'm working on a vuejs/express fullstack web app, and I know you can specify endpoints on the server like:
app.get('/', function (req, res) {
res.send('GET request to the homepage')
})
Which you can then hit from the client to display the home page.
But I'm wondering what about when you don't need to go to a 'route'? For example, you just want to send some data from client to server to do some calculations and then send data back to the client - do you still specify an endpoint e.g /FunctionName and access it from the frontend in the same way or is there some other way to call a function in the backend?
This is the 'express' way to define endpoints (or routes), regardless if it will return an html page like the example you've specified, or do some computation by calling other functions with user-specified parameters.
As a basic example:
app.post('/myendpoint', function (req, res) {
returnValues = callMyFunction(req)
res.send(returnValues)
})

Expose routes on different domains

I am struggling with something that doesn't look that hard : let's say I have 2 urls to access my server :
http://localhost:80/
and an external url
http://domain.com/internal/
Is there a way to do add a basepath internal if the forwarded host is equal to the external url host?
Something like :
app.use(function(req, res, next) {
if (req.headers['x-forwarded-host'] === 'domain.com') {
app.use('/internal', routes);
} else {
next();
}
})
There wont be any direct method as in a shortcut to work your way around for personal use cases.
I suggest this simple method though. Let's take example of app.get('/xyz') route.
This can be accessed locally via http://locahost:80/xyz or yourdomain.com/xyz via any application not hosted locally (Unless you make a call using your domainname in your own application).
Add a header element with every request when the call is internal.
Now, whenever our/xyz route is called check for that header element using a if condition and if the request is made internally you'll have that header element there and then you can simply use either res.redirect or any other method that you find useful (Exporting function in current route or anything else you find easy and needful).

KeyStone JS Account Controller

I understand MVC structure when coding in NodeJS. I started using Keystone JS recently, and I really like it. But, the way they set their controllers up, it seems that the controllers ONLY serve the purpose of rendering a view.
In an earlier project, I had an Account.js model and an Account.js controller. I'm trying to see how it would copy over to keystone.
So: How would I allow users to signup/signin/logout in a Keystone project (not into the Admin UI, but like a member of a regular site)? How would I make an Account controller (obviously with no view to render)?
There are lots of ways you can implement your own methods of authentication and account management in keystone since it is based on express.js.
You can then add an array of 'middleware' functions to routes which will run before passing the request to the controller.
e.g
Route before middleware added
app.get('/admin', routes.views.userAdmin);
Middleware Function
function isAuthenticated(req, res, next) {
// do any checks you want to in here
// CHECK THE USER STORED IN SESSION FOR A CUSTOM VARIABLE
// you can do this however you want with whatever variables you set up
if (req.user.authenticated)
return next();
// IF A USER ISN'T LOGGED IN, THEN REDIRECT THEM SOMEWHERE
res.redirect('/');
}
Route with middleware added
app.get('/admin', isAuthenticated, routes.views.userAdmin);
It's a very broad questions so I'd recommend you go and decide on the best way you'd like to do it yourself as everyone has their own personal preference. The search terms you want are 'express middleware authentication'. A lot of people use PassporJS http://passportjs.org/
Hope that helps :)

Use Settings of Used Middleware

By "setting" I mean "something that is set", similar to "setters" in Java & other OO languages, not Express's "application settings". Is there a way to access and ideally use "settings" set inside middleware use()d by the app? In particular, some middleware is a full Express app, like vhost and the new Router middleware that comes with Express 4.x. If you do most of your routing in a virtual host and want to access some route param from the main app, that could be a problem. This is especially true if you have several layers, like I'm having, and it would be inconvenient to export the setting all the way out to the main app.
So is there a way to access these settings from the main app?
In particular, some middleware is a full Express app
Express 4.x has a great new feature to get around this problem. You can now use express.Router directly. In cases where you used to use an entire routing path by using a second sub-Express object as middleware, now you can just use Router.
For anything else, I usually add properties to the request object, namespaced by the name of my app.
function (req, res, next) {
req.myApp = req.myApp || {};
req.myApp.someData='whatever';
next();
}
The next middleware in the line will have access to this variable. I use this to track unique connection IDs, assigned by the first piece of middleware and subsequently used by others.

Resources