Application-wide CORS restrictions not working [duplicate] - rust

I'd like my Rails 5 API-only app, for now running on http://localhost:3000, to only accept requests from my NodeJS front-end app, for now running on http://localhost:8888.
So I configured /config/initializers/cors.rb like this:
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins "http://localhost:8888"
resource "*",
headers: :any,
methods: [:get, :post, :put, :patch, :delete, :options, :head]
end
end
And I wrote this test:
#/spec/request/cors_request_spec.rb
RSpec.feature "CORS protection", type: :request do
it "should accept a request from a whitelisted domain" do
get "/api/v1/bodies.json", nil, "HTTP_ORIGIN": "http://localhost:8888"
expect(response.status).to eql(200)
end
it "should reject a request from a non-whitelisted domain" do
get "/api/v1/bodies.json", nil, "HTTP_ORIGIN": "https://foreign.domain"
expect(response.status).to eql(406)
end
end
The first test is passing as expected. But the second is failing with a response code of 200. Why?
(I'm not wed to a 406 response code by the way; just one that indicates the request will not be fulfilled.)

CORS configuration won’t prevent the server from accepting requests based on the value of the Origin request header. You can’t do that just through CORS configuration.
When you configure CORS support on a server, all that the server does differently is just to send the Access-Control-Allow-Origin response header and other CORS headers.
Enforcement of CORS restrictions is done only by browsers. It’s not enforced by servers.
CORS works like is: regardless of any CORS config you make on the server side, the server continues accepting requests from all clients and origins it otherwise would; and so all clients from all origins continue getting responses from the server just as they otherwise would.
So even when you see an error in browser devtools that a cross-origin request from your frontend JavaScript code failed, you’ll still be able to see the response in browser devtools.
But just because your browser can see the response doesn’t mean the browser will expose it to your frontend code. Browsers only expose responses for cross-origin requests to frontend code running at a particular origin if the server the request went to opts-in to allowing the request by responding with an Access-Control-Allow-Origin header which OKs that origin.
So for any requests with an Origin request header matching https://foreign.domain, the configuration snippet in the question should cause browsers to emit a message on the client side saying http://localhost:3000/api/v1/bodies.json can’t be loaded because there’s no Access-Control-Allow-Origin response header in the response (because your configuration causes the server to only send that header in responses to your whitelisted origins).
But that’s all you can do through CORS. You can’t prevent the server side from accepting and responding to requests from particular origins just by doing any CORS configuration on the server side. If you want to do that, you need to do it using something other than just CORS.

Related

Socket IO allows CORS request from curl, but not from client application

I am making an application in which i have a node backend, and an angular frontend.
I am using socket.IO to communicate between my client and server.
I was facing CORS issue, which i solved (tried to) as:
const io: SocketIOServer = new SocketIOServer(server, {
cors: {
origin: true
}
}); // only for development
But still, upon making my request from my client app (running in another port) gives me CORS issue.
So i went to my terminal, and made a request with curl,as shown here:
me#Desktop:~$ curl "http://127.0.0.1:5000/socket.io/?EIO=4&transport=polling&t=NV5sBAn"
0{"sid":"jAhPIEEkdy8EY8I_AAAD","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":5000}
This suggests me that curl is being able to access the server, and is not facing CORS issue.
In my client, i am trying to connect to my server as:
socket = io.connect('http://locahost:5000'); // server running at port 5000
Help me with my issue, so i can connect with my server.
Also on a sidenote: If the version of server.io in the app is 3, the curl request to the server is also failing. only upon server.io version 4, the curl request is passing.
The error in firefox if that helps:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://locahost:5000/socket.io/?EIO=4&transport=polling&t=NV5vi1_. (Reason: CORS request did not succeed).
EDIT: my issue is not being able to connect to the server with client. I showed the curl because it was suggested in the socket.io cors configuration webpage.
Because socket.io initiates its connection with plain http requests, it is subject to CORs restrictions. CURL does not enforce CORs restrictions (like the browser does) so that's why you don't see it there.
You have a couple options:
You can enable this specific CORs request in your server to permit it.
You can specify the {transports: ['websocket']} option for your socket.io connection in the socket.io client code that initiates the connection. This will tell socket.io to immediately start with a webSocket connection which is not subject to CORs.
Curl does not implement CORS security restrictions, thus it will always be able to connect. You have different ports for your frontend and backend which are considered different CORS origins. So you either need to set your allowed origins correctly on your server and make sure it handles the pre-flight requests, or have the process serving your frontend proxy requests to the backend so that everything is on the same url from the browser’s point of view
Apprrently, the issue was:
socket = io.connect('http://localhost:5000');
changing this to:
socket = io.connect('http://127.0.0.1:5000');
worked!! I have no idea why this name was not getting resolved!!

CORS-enabled server not denying requests

I am trying to use express Cors with my resitfy server and it doesn't seem to be denying requests coming from other ips. I am working locally so I tried setting origin to a random public ip but all of my requests are still going through
Here is my route:
module.exports = function(app) {
var user = require('./controllers/userController');
var cors = require('cors');
var corsOptions = require('./cors.json');
app.post('/auth/signup', cors(corsOptions),user.createUser);
app.post('/auth/login', cors(corsOptions), user.validateUser);
app.post('/auth/generateKeys', cors(corsOptions), user.generateKeys);
app.post('/auth/generateToken', user.generateToken);
};
and here is my cors.json file where I have set a random ip:
{
"origin": "http://172.16.12.123",
"optionsSuccessStatus": 200,
}
With cors set on the route I can see the following in postman but the request is still going through? I would expect an access denied response.
Access-Control-Allow-Origin →http://172.16.12.123
CORS configuration on its own isn’t going to cause a server to deny requests. You can’t cause server-side blocking of requests just through CORS configuration.
The only thing servers do differently when you configure CORS support is just to send the Access-Control-Allow-Origin response header and other CORS response headers. That’s it.
Actual enforcement of cross-origin restrictions is done only by browsers, not by servers.
So no matter what server-side CORS configuration you make to a server, the server still goes on accepting requests from all clients and origins it would otherwise; in other words, all clients from all origins still keep on getting responses from the server just as they would otherwise.
But browsers will only expose responses from cross-origin requests to frontend JavaScript code running at a particular origin if the server the request was sent to opts-in to permitting the request by responding with an Access-Control-Allow-Origin header that allows that origin.
That’s the only thing you can do using CORS config. You can’t make a server only accept and respond to requests from particular origins just by doing any server-side CORS configuration. To do that, you need to use something other than just CORS configuration.
CORS does not prevent anyone from sending GET or POST requests to your application or exposed API URL.
Instead, it indicates to the web browser that AJAX requests are allowed to this server, from the domain they are executed.
But only AJAX requests executed from a domain are CORS-controlled. Entering the URL in the web browser will not activate CORS: it is not a firewall.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
The order of event is:
Domain A executes AJAX on User's browser to request API URL on Domain B
User's browser sends a basic primary request to target Domain B and checks if CORS are allowed for Domain A
If allowed, AJAX request is executed otherwise null is returned

Specific Endpoint: Access Denied (no Access-Control-Allow-Origin header) on API Request in React/Redux App with Node

I cannot access a custom heroku API endpoint in a react/redux app. The heroku endpoint loads up fine in a browser, and I can see the network request coming back on my console, so it seems something in my app itself is preventing it from returning.
It's the classic 'No 'Access-Control-Allow-Origin' header is present on the requested resource' error, but what's perplexing is that I can use another endpoint (such as openweather's API) and don't get this error.
Do I need to use Express or other middleware to deal with Heroku specifically? I'm creating a store with ReduxPromise middleware right now and am using Axios to make the request. Or is there a server side configuration on Heroku that might change this?
Thanks for your help, pretty new to react/redux/node =)
This is a CORS issue, you need to add a cors configuration into your API request and accept the origins on the server side using access-control-allow-origin header and accepting the referrer url of the request.
These are my configuration options when using redux-api to make the requests, look at the documentation for your specific framework:
export const baseOptions = {
mode: 'cors',
credentials: 'include',
headers
}

Socket.io + Express CORS Error on localhost (not allowed by Access-Control-Allow-Origin)

I have a working node.js Express server to which I would to add socket.io support (allow javascript clients to connect via socket.io). I can connect to the express server via a Javascript $.get(), but the socket.io.connect() command fails due to a CORS error.
My testing machine is OSX with Apache to serve the client, thus port 80 is taken, so I have node.js/express running on port 8888. I added socket.io per the documentation:
var exp = express();
var server = require('http').createServer(api.server);
exp.listen(8888);
var io = require('socket.io').listen(server);
io.sockets.on('connection', function(socket) {
console.log('connection');
});
I properly see "info: socket.io started" in my node.js logs.
Then, on the client, I attempt to connect to the server...
this.socket = io.connect('http://localhost:8888');
this.socket.on('connect',function() {
socket.emit('install','test');
});
However, I'm getting a CORS error in the console in Chrome:
XMLHttpRequest cannot load http://localhost:8888/socket.io/1/?t=1358715637192. Origin http://localhost is not allowed by Access-Control-Allow-Origin.
HOWEVER, THIS works fine!
$.get('http://localhost:8888',function(e,d){
console.log(e,d);
});
So I double checked my headers, for both localhost:8888 and localhost -- both are properly returning the headers which (should) allow for the cross-domain requests...
Access-Control-Allow-Origin: *
Any ideas?
CORS is a very tricking thing to get working (or at least it was for me). I recommend this resource here: http://enable-cors.org/
Following what they do very carefully helped me. I also found that different browsers gave different visibility over the CORS request/responses which helped.
I found that Chrome was easier to get working than firefox, but firefoxes tools such as firebug, were quite nice to work with.
My gut feel from your information is that you might need your request to have an X-Request-With in your request attributes.
I also found using fidler to send the http requests allowed me to narrow my problems down to the server side initially and get that working. You will find browser enforce CORS, but something like fidler doesn't and thus provides another way of inspecting what is happening.
I definately recommend trying to break the problem in half so that you can see if it is server side or client side that is not behaving how you expect.
My problem was related to returning the same CORS response for the OPTIONS header as the POST or GET. That was wrong. Chrome allowed it. Firefox didnt. Any options request that is sent out will be sent out once, then in the future it will be cached and not resent (Which caused alot of confusion for me initially). For the options request you just need a standard response saying its ok to proceed, then in the post or get response i believe you want your cors responses there only.

enyo is giving me a "not allowed by Access-Control-Allow-Origin".and will not load content from nodejs server

I made the simple hello world NODEJS Server.
I have a enyo web service running in chrome that is trying to access the NODEJS server at http://localhost:3000
When is calls the onSuccess method, no data is loaded and the consule shows the following error
XMLHttpRequest cannot load http://localhost:3000/. Origin http://localhost:81 is not allowed by Access-Control-Allow-Origin.
I tested the nodejs server in the browser, it worked fine.
I tried to set the --disable-web-security, flag in chrome, it did not work.
Does anybody know how to fix this problem? If NOD.js is running on another server, would it work? This security is so confusing.
Ted
For security reasons, browsers limit the requests that a script may make via XMLHttpRequest.
Your requests will only succeed under the following 2 cases:
The origin of the URI that your script loads is the same as the origin of the page on which the script is executing (localhost:81 and localhost:3000 are the same host but different origins);
or, if your browser supports it, the server of the page being requested includes an Access-Control-Allow-Origin header which explicitly authorizes pages served from the origin in question (or pages served from all origins) to make XMLHttpRequests to it.
Try adding the Accesss-Control-Allow-Origin header to whatever is generating the response in your node code, adding a header in some code that looks like this:
response.writeHead(200, {
'Content-Type': 'text/plain',
'Access-Control-Allow-Origin' : 'http://localhost:81'
//allow anything by replacing the above with
//'Access-Control-Allow-Origin' : '*'
});

Resources