How to secure an ExpressJS RESTful API? - node.js

I was wondering if it is possible to secure an expressjs RESTful API that only a react native app and react website could access.
For exemple my server is running on port 8000, my react native app is on port 3000 and my website on port 5000. I want the server to listen only to requests coming from these ports.
Let's say I have a POST route to mydomain.com/signup I don't want users to make that post request using external websites or tools like Postman.
What would be the best way to ensure my mobile app and Web site are the only ones allowed to access my RESTful routes.

First off, you are a bit mistaken about how a request to your API works. When your react app on port 3000 makes a request to your server on port 8000, it's just a random incoming request. It doesn't "come" from port 3000. In fact, the incoming port number with be some randomly generated port with 5 or 6 digits. Outbound ports are dynamically generated by the TCP system and you can't tell what "app" it came from.
Second off, your RESTful API server is just a server on the internet. Anyone can make a request to it. Using cross origin protections, you can provide some limits about what can be done from browser Javascript (only allowing requests from your particular domain's web pages), but other requests (not from a browser) cannot be blocked this way.
So, any code jockey using any tool other than a browser can write code to your API. What someone like Google does is they require you to either have an APIKey that they issued to you or they require some login credentials (often a cookie from a previous end-user login) that identifies the user making the request as a permitted user using their system. Even with these tools, this just means that a permitted user is accessing the API, it does not mean that only your app is accessing the API. And, in fact, you can't really prevent that.
So, what most people do is they require a login or APIKey credential and they track the type of use of the API. If the use of the API seems appropriate (particularly the types and frequency of requests), then that use is permitted. If the use of the API does not seem appropriate (often too many requests over some period of time), then that particular credential or user may be blocked from accessing the service either temporarily or permanently.
Let's say I have a POST route to mydomain.com/signup I don't want users to make that post request using external websites or tools like Postman.
You cannot effectively do this. There are obstacles you can erect to make it more difficult like putting an expiring token in your web page and having your own use of the API include the token and then detecting if its a valid token, but a determined hacker will just scrape the token from the web page and still access your API using it from whatever programming tool they want.
What would be the best way to ensure my mobile app and Web site are the only ones allowed to access my RESTful routes.
You can't. Your API is on the web. Anyone with whatever credentials you require can access it.

Related

How to prevent others from using my REST API?

I've developed simple REST API using a expressJs. I'm using React as my client side application. So the problem is anyone can see my API endpoints because of react app is in client side. So they will also able to make request and fetch data from my REST API. (May be they will build their own client side apps using my API.) I've seen some question about this and couldn't find any comprehensive answer. How these kind of a security problem should be handled? Is it possible to give the access for API to only my client app? If not how huge brands that using REST API prevent that? (Also I don't have a user authenticating scenario in my product as well. People can just visit and use the website. They don't need to register).
Authentication can be a way but it can be bypassed. Another way is you can create a proxy server which strictly blocks cross origin requests, hence it blocks requests from other domains to make request to your API, and you can make your API call from that proxy server. In this way your API server endpoint will also be not compromised.
If, as you state in your comment, this is about users on your own website being allowed to use your site's API, while disallowing off-site use (e.g. other websites, wget/curl, etc) then you need to make sure to set up proper CORS rules (to disallowed cross-origin use of your API) as well as CSP rules (to prevent user-injected scripts from proxying your API), and you also make sure to only allow API calls from connections that have an active session (so even if you don't want user authentication: use a session managemer so you can tell if someone landed on your site and got a session cookie set before they started calling API endpoints).
Session management and CORS come with express itself (see https://expressjs.com/en/resources/middleware/session.html and https://expressjs.com/en/resources/middleware/cors.html), for CSP, and lots of other security layers like HSTS, XSS filtering, etc, you typically use helmet.

nodejs API restrictions ... Not allowed from postman .. same origin access allowed

I have created few API on nodejs a d want to consume in same nodejs app. Even I have ensure cross origin to my domain.
It's only preventing cross domain and not allowed API.
But when using postman it's allowed .
Please help to provide how to restrict my nodejs api to be used by my app internal in angular and should not allow cross domain and postman.
Cross domain protections are implemented only in a browser to protect end-user browser security. They do not apply to http requests made from Postman or from node.js or from any other programmatic tool, only from the browser.
There is no way to keep your API from being called by other agents besides your own web app. This is just the way of the web. For your web page to be able to use the API in the browser, that API has to be open to the public.
The usual way to provide some protections on such APIs is to require some sort of user login in order to use the API. Your own web app can have a logged in user and your server can require a certain login cookie be on the http request before your server will fulfill the request. This too can be used by 3rd party tools such as Postman, but they would have to first obtain an appropriate login cookie.
To prevent abuse even in these cases where they get a login cookie, you would need to track usage on your server and if you detect any irregular patterns or abusive patterns (often with some sort of rate limiting detection logic), then you can temporarily or permanently ban that user login.

Setup API that only your webserver can see it

So I want to have nginx serve up my react app that uses an API that is setup to make all the API calls for me. I want to do this so I can guard my API key and secret. So the API server is running on port 9001 and my react app is making api calls to to http://localhost:9001/api/v1/token. It works just fine. The issue I have is, how can I stop someone from doing the following to get a token?
curl -X POST --header "referer: http://localhost:8081" -i http://localhost:8081/api/v1/token
Thanks
If what you're asking is how you allow only your react app to use your API server, then the answer is you can't really.
Any request made from the browser has to be made to a server that can be reached lots of other ways (such as your Curl example). You can't allow only requests made from your React code and disallow all other attempts to talk to your API server because at the lowest level, these are all just http requests. Any determined hacker can just watch what the browser sent from your React app and make an http request that looks just like it. This is a fundamental design characteristic of how apps in a web browser work.
That said, there are some things you can do to "protect" your API server from abuse.
1. Require some form of account or authentication. This will at least require a hacker to make an account in your system and use that account to access your API server (more on this later).
2. Implement rate limiting so that an individual account (detected based on the credentials in the previous step) is only allowed certain frequency or pattern or access. At the very least this protects your API server from being overly abused by one bad actor.
3. Implement abuse control. If one particular account is regularly abusing the API server (hitting rate limit controls and generally using way more resources on your API server than any reasonable normal browser user ever would), then you can ban that account.
Services such as Google maps implement all three of the above in their efforts to protect the integrity of their API servers.
There are other techniques such as embedding an ever changing token into the web page that is then required with each subsequent call to the API server, but a determined hacker will just scrape the token from the web page and then use it until it expires so this is really just another obstacle for the hacker to get around, not an actual roadblock.

Should we have same or different route for external and local request

I'm building an externalized API for developers who want to develop their own app based on our API. Here is my question; the API provides the ability to let other developers make external requests to our server, but should we handle the same request in same route for local and external request for same function?
For example:
we have a login route in API /api/v1/login this route provides the ability to make login request to this API in other site but when our local site want to let user login should we use the same path /api/v1/login or we should make another route for local request /auth
Is there any security issue if using the same route for the external request?
The main security issue would be that there wouldn't actually be a difference between your external API and your "local" API. If both are using the same paths to do the same things, and are using the same backend functionality to do so, they aren't different. This isn't really a security problem so long as you are still properly controlling API access appropriately, i.e. through API keys, though your client would have to use those same access controls.

What clients can / can't access a RESTful web service by default?

I am currently developing an API that will be launched into production in a matter of weeks. I am relatively new to REST, started reading about CORS - and realized that it could impact me.
What conditions will a REST service not be accessible to a client? I have been using sample html/js on the same server, and through Postman - a google chrome addon - to access my API. I have had no issues so far.
When the API goes live, it will be hosted at 'api.myserver.com'. Requests, at the beginning, will come from 'app.myOTHERserver.com'. Will these requests be denied if I do not use a CORS-friendly approach like JSONP or special 'access-control' headers that permit my domain?
What about accessing rest APIs from other non-browser clients? Such as a C# application? Are these requests permitted by default?
Assuming I do need to add 'access-control' headers server-side, to permit the scenario described above when my API goes live, is it better (performance-wise) to let your web server (NGINX in my case) handle the headers, or should I add them through PHP or NodeJS?
This is more about the same-origin policy applied by web browsers than it is about RESTful APIs in general.
If your API is intended to be used by web applications deployed on a different origin host/port than the API, then you have these options:
Respond with appropriate headers that allow for techniques like CORS to work.
Have the web server which serves up your web content (in your example, app.myOTHERserver.com) handle your REST API requests too by proxifying your API requests from the web server through to the API server. For example, you could have your API exposed on your web server under the URL /api, and then it's just a matter of setting up a web proxy configuration that forwards requests under that URL to your API server.
Use JSONP or other techniques.
If your API is going to be used by non-web applications, you have nothing to worry about. This is only a restriction applied by browsers when running JavaScript code to make sure that the user hasn't inadvertently clicked on a phishing link with some hackery in it that tries to send their PayPal password to Pyongyang.
When the API goes live, it will be hosted at 'api.myserver.com'.
Requests, at the beginning, will come from 'app.myOTHERserver.com'.
Will these requests be denied if I do not use a CORS-friendly approach
like JSONP or special 'access-control' headers that permit my domain?
You can specify what clients can access your web service to an extend. Assuming you're using Express: How to allow CORS?

Resources