Calling insecure endpoint from a website runs under HTTPS - nginx - rest

My application is running under HTTPS with a valid certificate from one of the known authorities. Unfortunately I am using a third party API which doesn't support HTTPS.
The result is the known message Mixed content: mydomain.com requested an
insecure XMLHttpRequest endpoint.
Is it possible to add an exception to the web server to allow calling this API insecurely!! I am using Nginx BTW.
If not what what can be other possibilities to solve this problem.
I have a solution but I don't like it because it will be a performance drawback:
Implement an API which acts as proxy, receive the requests from the application through HTTPS and make the requests to the third party API throw HTTP.

I too had this issue. Everything on a page should come and request https if you are using https and don't want warning/errors. You don't need to implement an api to proxy if you are using nginx. Whatever you implement will be performance hit as you correctly surmise. Just use proxy pass in nginx.
In our configuration, we have :
location /thirdparty/ {
proxy pass http://thirdpartyserver/;
}
Notice the trailing slash in proxy pass, I keep all third party api which are http in https://myserver/thirdparty/requesturl. Trailing slash removes thirdparty while making request. So it becomes, http://thirdpartyserver/request
Official reference: http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass

In order to allow mixed content, the individual users must allow it in their browsers. Allowing HTTP content from one source is enough to compromise the security of HTTPS, so browsers forbid mixed content by default. The solutions I see are:
Getting rid of HTTPS (which I would NOT recommend)
Doing what you suggested and proxying requests through (this still isn't great security-wise)
Get rid of the HTTP content
Google has some recommendations for developers under step 1 (but they are basically echoed above): https://developers.google.com/web/fundamentals/security/prevent-mixed-content/fixing-mixed-content#step-1

Related

http-only site to test REST requests?

After the latest move by httpbin to HTTPS, apparently all sites that accepted test REST requests have disappeared. I've checked all mentioned in this post, and either they do not allow all kind of requests, or have also moved to HTTPS. For Raku modules such as this one, LWP::Simple, we need a HTTP-only site due to problems with certain operating systems. So is there any site left or will we have to roll out our own server?
You can use http://eu.httpbin.org. This URL doesn't redirect http to https.
http://www.neverssl.com/ and http://neverssl.com/ are another good options. They will never use HTTPS/SSL.

How to protect REST API with CORS?

I am developing a web application where data will be accessible both to frontend and to various clients (curl & co.) through REST API. Both frontend and backend will be on the same domain. I would like to protect my frontend with CORS, which presents a dilemma for me. If I set Access-Control-Allow-Origin to * then all other clients will be able to access API, but my own frontend will be more exposed. On the other hand setting it to my domain forces clients to supply (fake) Origin headers and effectively disallows using browsers as clients (via frontend on different domains).
How is this usually solved? Should I use two different endpoint for API, one for public access and the other for use with my frontend? I would appreciate some advice.
I would like to protect my frontend with CORS
CORS doesn't protect anything in the frontend, CORS is a way to prevent cross-site scripting from web sites which are not authorized. The CORS headers are effective only for browser's XHR calls. It will not prevent direct loading of resources.
If I set Access-Control-Allow-Origin to * then all other clients will be able to access API, but my own frontend will be more exposed.
IMHO you frontend will be accessible as before. The CORS headers are effective only for browser's XHR calls
On the other hand setting it to my domain forces clients to supply (fake) Origin headers and effectively disallows using browsers as clients (via frontend on different domains).
Not really.
There are several options:
You can have a list of allowed hosts for each API client (effective you set the origin header based on the client's authentication) This is what many of API providers do (FB, Google, Amazon, ..)
the browser (in the XHR calls) sends the Origin header and you could check and sent or deny the hostname from the Origin header
And non-browsers clients are not restricted by the CORS headers.
Should I use two different endpoint for API, one for public access and the other for use with my frontend? I would appreciate some advice
As written in the comments - assuming the functionality is the same and users are authenticated, then IMHO there is no point in having separate services for internal / public use.
These all are answers for particular questions, however I am still not convinced it is clear what/why/how you want to achieve.
CORS is relevant only for browsers & HTML. curl doesn't care about it. So if you restrict your service to be accessed only from your domain, then other sites won't be able to access it.
To make your service available for them - those sites could set up nginx or apache to forward some of the traffic to your service. So 3d-party sites will access their own host with their own CORS configured and their host will communicate with your service.
Another (similar) solution would be for you to set up 2 host names (subdomains?) that lead to the same service. And expose one to your own site (with strict CORS) and the other - for external clients.

Confusion about REST API calls

I have an api gateway installed that I'm trying to program against. Requests work when using apps like Postman but when I try to connect through code in the form of XMLHTTPRequests I get 401... No 'Access-Control-Allow-Origin' header is present on the requested resource. saying that the server doesn't allow cross site calls.
Maybe I'm not fully understanding how this works but it seems that apps like Postman circumvent this somehow. Whereas when I'm trying to access the api from a local file in my browser I bump into this problem.
Do I need to host the webpage I'm calling from to get this to work? Or am I missing something else here?
When the browser issues a XMLHTTPRequest, it checks if the origin (i.e. the domain) of that request is allowed by the endpoint to send requests. The check is done by a preflight request, i.e. a HTTP OPTIONS request which should provide a response containing a Access-Control-Allow-Origin header with the domain originating the request (or * to allow all domains).
Since this is a security measure of the browser, mainly based on the fact that browsing web pages the user may not know which requests are sent to which endpoints, Postman simply does not need to apply it because its requests are explicitly sent by the user himself.
https://developer.mozilla.org/en-US/docs/Glossary/CORS
https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request

Does a RESTful API need CORS implementation anytime?

I struggle around with CORS implementation in my client-server project. CORS means, that calls from other origins (ex. other domain) only allowed if the header contains the CORS value.
So, for example if I host a website on www.domain.com and call an RESTful API on the same domain, everything is fine.
But if I develop an API for an mobile application for example, the mobile does not have the same domain of the API. How could that work together? Does I need everytime the CORS implementation in my service?
The question comes up, since I develop an Angular 2 application, that is running in dev on localhost:4200 and my API runs on localhost:8080 (build with Spring Boot). So the client throws an exception, because it's not the same origin (different port).
The Goal is to host my API on an root server somewhere in the internet, and the client on different webspace provider (because it's just a single Page Application). The api runs with http://1.2.3.4:8080/api/v1 and the client with http://www.example.com:80/myPage
So, does I need to implement Cross-Origin everytime? Or is there another way to realize that?
Due to security concerns, browsers enforce same-origin policy i.e., a script (typically AJAX calls) running in a web page cannot access data from another page residing in a different domain. In some cases, this can be restrictive. CORS (Cross Origin resource sharing) is a W3C specification supported by most modern browsers to specify when it is safe to allow cross origin requests.
In Spring boot, enabling CORS is as easy as adding the #CrossOrigin annotation. This annotation can be added at method level to enable just for that particular request mapping or at the class level to enable for the whole controller.
You could list the domain and port to be allowed by adding an "origins" attribute to the annotation. If it is not specified, all origins are allowed by default (better to avoid this for security reasons).
Below is an example to enable CORS for example.com domain and port 80 at controller level
#CrossOrigin(origins = "http://www.example.com:80")
#RestController
#RequestMapping("/yourmapping")
public class YourController {
}
Yes, if you are developing an API and want to make it public and want mobile users or other site consumers use it, you should set CORS for any site (*) , always. You can read more info here:
https://spring.io/understanding/CORS (no longer functioning)
https://auth0.com/blog/cors-tutorial-a-guide-to-cross-origin-resource-sharing/

Request builder call not returning when using ssl(https)

I am using GWT. Currently using gwt-rpc to for login authentication. For only login purpose i want to use ssl(https) and so instead of using gwt-rpc i am trying Request Builder and calling a servlet with https.
When in Servlet URL i use protocol as http the request builder works perfectly and response returns to client side(onResponseReceived ). but when i use https in the servlet url then the servlet is gettting called but the response is not returning to the onResponseReceived method of request builder.
my url with http looks like : http://localhost:8888/myproject/myservlet
and with https it looks like :https://localhost/myproject/myservlet
Please give any suggestion or is there any other way to do it.and also is it possible to use ssl over gwt-rpc.
Browser Same origin policy is blocking your requests.
Your page was requested over http, but you are now making an ajax call over https. This is a violation of same origin policy.
To get around, you should serve your original html/servlet over https. This does have a performance cost, but it is the only way to build a secure website.
I'm not familliar with GWT and Request Builder, but whenever I have had problems with HTTPS connections from my code it has come down to certificates and having the right certificate installed in the client or telling the client code where to find the certificate in order to encode the call.
That would be the first avenue I would want to explore in your situation.