pkpk pkpk - 5 months ago 29
Node.js Question

Nodejs accessing routes from external users and internal processes

I have an architectural question.

Lets say I have a route '/tickets'. I can easily authenticate users that are accessing this route using passport. I can further protect this route via acl.

Now let's say my internal app or a process want to access this same route. I'm thinking I might only have one option. I have to create a separate user/password with right role and have my internal app or process make an HTTP call to this route using this separate credentials.

So, is this a right way to access internal APIs ?
any other suggestions that might be useful ?

Thanks

Answer

There are lots of different options for routes that are only accessible internally:

  1. Create a different server on a different port, but in the same process that implements the private routes and block access to that port at your firewall. This is my favorite option because it's really simple to do right. You create a second http server process on a non-standard port (like 8000 or something like that) and you make sure your firewall only allows public access to port 80 or 443. You then put all your internal routes on the port 8000 server. But, since it's in the same process as your public server, you can still access all the sme data. With one simple firewall rule (that is probably already implemented by default), you block access to all private routes.
  2. Authenticate all routes, use different credentials for internal routes. Here, you have a different set of credentials that is kept internally and is used only for your internal routes. Since nobody in the outside world has those credentials, they shouldn't be able to use them.
  3. Block public access to internal routes at the networking level. Here you would use either a proxy or a firewall to block access to specific internal routes at the networking level. So, if your incoming firewall saw a request for /admin/whatever, it would just block access to anything starting with /admin. Internal routes could be used freely with either with or without credentials, but could only be used from within the private network of your server. They couldn't be access from the outside.
  4. Allow access only to known public routes at the networking level. This is just the reverse of option 2. Here you have to specifically tell your firewall/proxy which routes the public is allowed to access.
  5. Allow access to private routes only by certain IP Addresses. Here, you could deny access to any private route if the source IP address was not a local IP address on your local network. This is just a different way of implementing 2 or 3. This can be made fairly restrictive to only allow access from one or a very specific number of internal IP addresses if you want.

For additional security, you can also combine various options which is sometimes useful for preventing internal attacks on your own infrastructure either from a mal-employee or from some other piece of compromised infrastructure on your own private network.

For example, you could combine options 1, 2 and 5. You'd create a separate server port that was not accessible from the public internet and you'd authenticate every request to it with internal-only credentials and you'd only allow access to it from specific internal IP addresses. I'm not saying you have to combine all those, but I'm giving you the idea that these are not all mutually exclusive. My favorite would be to combine 1 and 2.

FYI, if you want to have private access to the same functionality such as /tickets, but with different access, you can use the 2nd server that is only accessible internally (as described in option 1 above) and just have a /tickets route on it that has different access control. The two separate servers can share all the same /tickets implementation (just put the implementation in a function that the two can share) except they would have different route definitions on the two servers that define the authentication required. You could even have the private server set a flag on the request object that indicates to the rest of your code which entry point the route was called from (public or private) so it could branch based on that information.