Strategy for CORS - issue with IE10 : xhr status returns 0 for HTTP 401 - apache

I have the following setup on my server:
Apache HTTP Server is serving a BackboneJS frontend application
Apache Tomcat is serving a Java based backend (CORS enabled).
Everything is running on a single server that I have full control over.
I'm currently using com.thetransactioncompany.cors.CORSFilter in the Java based backend to enable CORS. Everything seens to be working fine.
My frontend has the following code to redirect the user to the login page in case an un-authenticated REST call occurred:
$.ajaxSetup({
statusCode: {
401: function(){
window.location.replace('/#login');
},
403: function() {
window.location.replace('/#denied');
}
},
cache: false
});
Everything works fine on all major browsers except for IE10.
In IE10, when the non-authenticated users calls the REST serverm the server returns an HTTP 401 (as it should). The XHR object I'm seeing in the IE debugger hoewever seems to have translated this into status = 0. (On chrome you can cleary see that it has status = 401.
This appears to be a bug in IE10 where IE10 is treating HTTP status 401 as a network error. The console shows:
SCRIPT7002: XMLHttpRequest: Network Error 0x80070005, Access is denied
Is there a way to workaround this ?
I can add handling for statusCode 0 in the ajaxSetup but that seems more of a hack.
Is there a way to disable CORS altogether through some kind of Apache / Tomcat configuration ?
Currently my apache configuration is setup using vhosts so that the following public URLs map their corresponding internal hostname / ports.
http://mywebapp.com -> http://myrealservername:8080/ -> /var/www/http
http://myrestapi.com -> http://myrealservername:8088/ -> /usr/local/tomcat/webapps/restapi
Would it be possible / advisable to have Apache
continue serving the static webapp from http://mywebapp.com/restapi
exposing the REST API on http://mywebapp.com/restapi (keeping it "inside" the webapp).
If such a setup were possible I wouldn't need CORS anymore ? It would keep things a lot simpler while increasing browser support ?

Related

Manage CORS between Google App Engine & Google Cloud Function

I'm trying to set up a new instance of a simple App Engine which communicate with a backend-function hosted on Google Cloud Function. The App Engine is protected with IAP, and the Google Cloud Function is private only. The GAE use Angular Framework and GCF use Node 14 with Express
.
I can't access to my GCF from the App Engine because the requests are blocked by CORS.
Access to XMLHttpRequest at '' from origin '' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I tried the popular solutions on the web :
Use the cors librairie on the GCF. So I had on my GCF
var cors = require('cors')
app.use(cors(cors({ credentials: true, origin: true })))
And I also add this line for every request
res.set('Access-Control-Allow-Origin', '*')
Add the http-header on my app.yaml
handlers:
- url: /(.*\.[A-Za-z0-9]{1,4})$
static_files: dist/\1
upload: dist/(.*\.[A-Za-z0-9]{1,4})$
http_headers:
Access-Control-Allow-Origin: "*"
- url: /(.*)$
static_files: dist/index.html
upload: dist/index.html
http_headers:
Access-Control-Allow-Origin: "*"
But I still get the same error message.
EDIT : so the first problem was due to an authentication issue, that why the error have the same response. So I decided to deploy the 2 apps on App Engine to simplify communication between the 2 services.
You can now have full access to the HTTP Request/Responses by setting
the appropriate CORS headers as per this documentation.
Just so you know the reason for the error you are facing, it is
because when your web browser is calling a service that is in a
different/cross domain, it doesn’t make a HTTP request right away, it
rather starts with making an OPTIONS request( a preflight request)
and compares the value of Access-Control-Allow-Origin header in the
result with the current domain i.e. it checks for this (req.method
=== 'OPTIONS') in the headers and if the header value matches the host, the actual call is made, otherwise the action is stopped and
the error as the one above is thrown.
To have a thorough understanding of the above concept, have a look at
this stackoverflow answer and read this article for more insights.

How can I start my Cloud Run App without HTTPS

I want to deploy an webapp for internal use only. This webapp is firing POST requests to other internal services. The problem is that the services are not running with TLS. The deployed webapp on Cloud Run has HTTPS activated by default. Therefore I can not launch any HTTP POST request to the services.
Any idea how I can deploy the app without TLS/HTTPS active?
Code snippet:
console.log('Starting Import: ' + this.urlString)
const xmlHttp = new XMLHttpRequest()
xmlHttp.open('POST', this.urlString, true)
xmlHttp.send(null)
console.log(xmlHttp.responseText)
Log:
Starting Import: https://34.95.76.221/importer/start/CATALOG001?file=test.xml
Chrome console error:
Importer-Controls.vue:103 POST https://34.95.76.221/importer/start/CATALOG001?file=test.xml net::ERR_CONNECTION_CLOSED
You are trying to make an insecure request from a secure context. You either need to enable SSL for your "internal services" or you need to build a service that proxies the request from HTTPS->HTTP.
For example, you could make a simple Cloud Run app that wraps the HTTP request and performs it on the backend instead of on the frontend. Then your frontend could make an HTTPS request to the proxy.

Chrome DevTools Approve Network Requests before executing

I'm looking for a way in Chrome DevTools (or any equivalent) to control the HTTP requests done by my web application:
I want to approve HTTP requests before executing, or let them fail in an unexpected way (give it status 500 or something).
USAGE EXAMPLE: Testing unexpected behavior
Does anyone know a way to achieve this.
I see 2 possible solutions to achieve this goal on the client side:
Use the Request-Blocking panel from the Drawer (Open Chrome DevTools -> Esc -> '...' -> Request blocking
This is completely out-of-the-box and works for most "offline-first" use cases.
Use a service worker. They are basically a way to proxy requests and respond individually (e.g. by responding with a 500-er). You might want to enable/disable such a debugging-feature by using Chrome Devtools Snippets (Open Chrome DevTools -> Sources -> Snippets) as you don't want your requests to fail all the time :)
First you need to register your serviceworker like this:
if('serviceWorker' in navigator) {
navigator.serviceWorker.register('/path-to-service-worker.js').then(function(registration) {
// registration successful
}).catch(function(err) {
// registration failed
});
}
Afterwards reload the browser (or install your service-worker in the DevTools -> Application -> Service Workers) so that your service-worker.js is active, may listen to the 'fetch' event and proxy the requests for this domain like this:
self.addEventListener('fetch', function(event) {
// this will set a breakpoint in chrome devtools, allowing you to manually edit the response
debugger;
// alternatively you could reponse with an error response like this:
event.respondWith(
new Response(null, {
status: 500
})
);
});
Sidenote: Due to security restrictions in the browser serviceworkers only work over https and on localhost.
Further information:
https://developer.mozilla.org/en-US/docs/Web/API/Response/Response
https://developers.google.com/web/fundamentals/primers/service-workers/
You can use Requestly Chrome extension to Redirect, Cancel, Block, Modify headers,... of the requests.
To approve requests before executing e.g. for AJAX requests create a redirect rule and point it to a static JSON file or another script.
To block a request use cancel request feature and set a custom pattern.

POST /token 400 (Bad Request) with ember-cli and ember-simple-auth

I just setup the example from https://github.com/simplabs/ember-cli-simple-auth-example using Cloud9 and I get a 400 Bad Request error when I try to login.
I'm pretty sure this is due to fact that Cloud9 only opens port 80 (as referenced in this note from http://log.simplabs.com/post/90339547725/using-ember-simple-auth-with-ember-cli:
As the OAuth 2.0 authenticator would by default use the same domain
and port to send the authentication requests to that the Ember.js is
loaded from you need to configure it to use http://localhost:3000
instead.
Unfortunately I don't know how I might work around this. Any ideas?
Add the host to the whitelist in the config:
window.ENV['simple-auth'] = {
crossOriginWhitelist: ['http://some.other.domain:1234']
}
More info in the Cross Origin Authorization section of the docs

Using stomp.js over sock.js with ActiveMQ-Apollo does not seem to work

I am working through some samples in the ActiveMQ-Apollo installation and playing around with the examples/websocket.
In this file, Stomp.js is being used to establish connection:
client = Stomp.client(url);
The example works fine and I am able to see the messages being sent and received. The issue, is that Stomp uses default WebSocket which may not be available at times. So, I wanted to integrate with SockJS client library. According to the example for StompJS on this page (http://jmesnil.net/stomp-websocket/doc/) it should be possible with this code:
<script src="http://cdn.sockjs.org/sockjs-0.3.min.js"></script>
<script>
// use SockJS implementation instead of the browser's native implementation
var ws = new SockJS(url);
var client = Stomp.over(ws);
[...]
</script>
The above code appears to execute correctly, however, later I see the following errors:
XMLHttpRequest cannot load ws://mylocaldomain.com:61623/info. Cross origin requests are only supported for HTTP. sockjs-0.3.js:807
Uncaught Error: NetworkError: DOM Exception 19
Then, I see the debug window show this message:
Opening Web Socket...
Whoops! Lost connection to undefined
I am serving the page from mylocaldomain.com:80, and the ActiveMQ Apollo server is running on the same machine, but listening on port 61623. I have also grabbed the latest version of StompJS (from dist directory on github) as well as SockJS directly from cdn.sockjs.org.
I tried this example on latest Chrome and Firefox (on OSX) and the same thing occurs. No connection is established.
Again, going back to the standard example which ships with the Apollo works fine, but I would like to find out why StompJS over StockJS is failing.
Has anyone seen this issue?
Thanks.
-AP_
You need to modify the ActiveMQ-Apollo web configuration to support Cross-Origin-Resource-Sharing (CORS) as described here:
Enabling CORS
W3C CORS Specification
Basically the server needs to do the following things:
Support the HTTP OPTIONS request (aka CORS pre-flight request) that is sent by browsers for Cross Domain requests. This includes responding to the OPTIONS request with:
Access-Control-Allow-Origin header (for example: "*" which means allow all origins)
Access-Control-Request-Method header (for example: "GET, POST, PUT, DELETE, OPTIONS")
Access-Control-Allow-Headers (for example: "X-Requested-With,Origin,Content-Type, Accept")
The handling of HTTP OPTIONS can typically be done using a single Web Filter matching filter pattern "/*".
See also "cors_origin" WebSocket connector URL query parameter supported by ActiveMQ Apollo 1.7