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?
Related
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.
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.
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.
I am working on web application that has angular 4 on frontend and WEB API on backend. This application is hosted on MS Azure and until now we didn't have any issues.
Currently we need to integrate with one payment provider. During payment user is redirected to his payment page, and if everything goes well user is redirected back to our web site. Beside the browser redirect (which may fail) payment provider supports server to server call (HTTP GET). In this way they make sure we get information about the transaction. The problem here is that instead of one call to our Web API backend we get always two calls. After checking the request origin IP addresses I concluded that there is two origins (one is payment provider address and another is IP located in USA, which I assume belongs to MS). This looks to me like a routing problem, but I am not very experienced at this.
Did anybody have similar problem on Azure while hosting web application ?
According to your decription, it seems that fails for cross domain request. Azure website is supposed to manage CORS for you.
I think you missed a handy Azure website blade: Specify the origins that should be allowed to make cross-origin calls (for example: http://example.com:12345). To allow all, use "*" and remove all other origins from the list. Slashes are not allowed as part of domain or after TLD.
Cross-Origin Resource Sharing (CORS) allows JavaScript code running in a browser on an external host to interact with your backend. Specify the origins that should be allowed to make cross-origin calls (for example: http://example.com:12345). To allow all, use "*" and remove all other origins from the list. Slashes are not allowed as part of domain or after TLD.
I'm interested to know what methods people use to secure their webservices from unauthorized web service consumers.
There is a protocol specifically for web services security WS-Security. I've used parts of it in the past but at the time there was not a lot of support for it in .Net so it was a lot of work.
Currently with .Net I use SOAP Extension Headers. I have one web service call to authenticate and get a session token and then include that token in a SOAP header for every subsequent call, somewhat similar to this example. Of course all the request must travel over TLS to keep them from being compromised.
I usually require either a user id/password to be sent each time, or return a token from the first authenticated connection that can be used subsequently.
Nothing fancy. Pretty similar to standard web app login.
I've used both SOAP headers and method parameters to pass user credentials -- .NET makes using the SOAP headers pretty easy, but I had issues with this using Java (several months back). I also do some IP-based filtering if the service is not intended for client (browser) use, but rather from backend web servers. Public, browser consumable web services are often protected by session cookies -- i.e, requires a valid logon to the web site, then the standard session authentication mechanism is used for requests via AJAX to web services.
You can use network appliances such as IBM's DataPower or Vordel if you don't want to handle in your own application.