AngularJS and rails cors headers not working - ruby-on-rails

Im trying to build an angular spa but have trouble with cors. My api runs on rails.
GET requests works without problem but POST, PUT, DELETE does not work. The message is:
XMLHttpRequest cannot load http://localhost:3001/api/resources. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8888' is therefore not allowed access.
In rails I have a before_filter with this code:
headers['Access-Control-Allow-Origin'] = '*'
headers['Access-Control-Allow-Methods'] = 'POST, PUT, DELETE, GET, OPTIONS'
headers['Access-Control-Request-Method'] = '*'
headers['Access-Control-Allow-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept, Authorization'
And in routes:
match '/*path' => 'sessions#home', :via => :options
In angular config I set this:
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
Any ideas on this? Im on mac, localhost btw
EDIT
This message is shown in headers in chromes network tab:
CAUTION: provisional headers are shown

The problem seems to be related with the rails configuration.
Here it is stated:
...We may want to disable CSRF protection for APIs since they are typically designed to be state-less. That is, the request API client will handle the session for you instead of Rails....
Though not with Angular (which I think the problem is irrelevant), this repo (that I recently prepared) may help for anyone that runs to this issue. It has a step by step guide to prepare a skeleton for a Rails SPA that uses CORS.

There are options to disable web security in Chrome to allow cross domain requests, but that is never the best way to go about it.
On a mac:
open -a Google\ Chrome --args --disable-web-security
Or try with dataType: 'JSONP' in your ajax call.

Related

Setting CORS headers do not solve my CORS problem

I'm trying to call an endpoint(POST https://target-endpoint.com/authentication) from another origin(https://origin.com) with below header settings, but CORS error has remain raised.
Is there any mistake in my settings?
authentications_controller.rb
def create
response.headers['access-control-allow-origin'] = 'https://origin.com'
// some impl
end
routes.rb
Rails.application.routes.draw do
post :authentication, to: "authentications#create", via: :options
end
error in chrome console
Access to fetch at 'https://target-endpoint.com/authentication' from origin 'https://origin.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
error in chrome network tab
If you have any idea, please let me know.
Thanks,
other conds.
heroku, with stack 18
ruby 2.6.4
rails 6.0.4.8
Before browsers make a cross-origin POST request, they first perform a so called CORS-preflight request to make sure that the target of the POST allows the request.
For that, browsers make an OPTIONS request to the URL and check the CORS headers of the response. Only if the respone headers of this preflight request indicate that the request is allowed, browsers will perform the actual POST request.
For you, that means that your create action (for the POST request) won't receive a request unless you also reply to an OPTIONS request first.
While you could implement this "by hand", it is usually a much better idea to use existing CORS implementation such as the rack-cors gem.

Value of 'Access-Control-Allow-Credentials' header in response is '' which must be 'true'

Have my backend deployed to heroku and my frontend deployed to netlify. I can't get past the landing page and login page on my netlify app link, even though my site worked fine before trying to get it deployed. I am seeing this console error several times when I try to login to my app on netlify and fail to do so:
Access to fetch at 'https://photo-sharer-backend.herokuapp.com/api/v1/get_current_user' from origin 'https://photo-sharer-kkirby16.netlify.app' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'.
photo-sharer-backend.herokuapp.com/api/v1/get_current_user:1 Failed to load resource: net::ERR_FAILED
Tried putting mode: "no-cors" in my fetch requests.
Tried putting "Access-Control-Allow-Credentials": true in headers object of all my fetch requests.
Tried putting config.hosts.clear in the module within config/application.rb
Still haven't fixed this error with trying those things. There is also not much online for this. From something I saw however it seems I may need to change something on the backend so that the response has the header, rather than focusing on frontend changes. Possibly I need to change my cors.rb file? Does anyone have ideas how I can fix this error?
First time trying to deploy a site and I would really appreciate any help.
Also, here is my cors.rb file:
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins "https://photo-sharer-kkirby16.netlify.app"
resource "*",
headers: :any,
methods: [:get, :post, :put, :patch, :delete, :options, :head],
credentials: false
end
end

Rails AJAX post form from HTTP side to HTTPS

I'm having a problem submitting an AJAX form (it is a sign-up modal form, that ideally, should be available on all of the pages) from HTTP (unsecured) to HTTPS (secured) part of the site.
The problem is - I'm getting status "200 OK", but no actual response is available (hard to debug actually) and nothing happens after it (but it should).
If I do the same request from one of the secured (HTTPS -> HTTPS) pages - it works totally fine.
Also in the log file I see following message: "WARNING: Can't verify CSRF token authenticity".
I tried skipping this CSRF filter, but no difference.
Can it be fixed somehow, apart from enabling SSL on the entire site ?
Fixed the problem myself by applying an after_filter to corresponding controller actions:
def access_control_header
headers["Access-Control-Allow-Origin"] = "*"
headers["Access-Control-Request-Method"] = "*"
end
Easy :)

How to respond to OPTIONS HTTP Method in rails-api?

I'm using rails-api to build a public json api.
I would like to respond to OPTIONS HTTP Method to take advantages of Cross-Origin Resource Sharing.
http://www.w3.org/TR/cors/
I'm doing this:
headers['Access-Control-Allow-Methods'] = 'POST, PUT, DELETE, GET, OPTIONS'
It works, but some URLs does not support all HTTP methods. In those cases I'm lying.
I don't want to configure Access-Control-Allow-Methods for each URL.
Is there a way to respond Access-Control-Allow-Methods based on my routes?
check out the rack-cors gem, it allows you to configure it like a routes file
https://github.com/cyu/rack-cors

Rails, REST Architecture and HTML 5: Cross domain requests with pre-flight requests

While working on a project to make our site HTML 5 friendly, we were eager to embrace the new method for Cross Domain requests (no more posting through hidden iframes!!!). Using the Access Control specification we begin setting up some tests to verify the behaviour of various browsers.
The current Rails RESTful architecture relies on the four HTTP verbs: GET, POST, PUT, DELETE. However in the Access Control spec, it dictates that non-simple methods (PUT, DELETE) require a pre-flight request using the HTTP verb OPTIONS. In addition during testing we discovered that Firefox 3.5.8 pre-flight POST requests as well.
My question is this. Is anyone aware of any project for the Rails framework working to address the issue? If not, any opinions about the best strategy to support the OPTIONS method, since it has to support the routes for all the POST, PUT, DELETE methods?
I released a Gem a couple of days ago that implements CORS support via a Rack Middleware:
http://github.com/cyu/rack-cors
Regarding preflight CORS requests, I couldn't get preflight requests working in Chrome (through simple CORS requests work fine). Searching around the Internets suggests that it might not be supported. I've asked questions in the Chrome forum about this, but haven't heard a response yet.
This is from Spine js documentation
CORs Rails integration
Let's create a cor method, which will add some of the request access control headers to the request's response.
Add the following to app/application_controller.rb:
before_filter :cor
def cor
headers["Access-Control-Allow-Origin"] = "js-app-origin.com"
headers["Access-Control-Allow-Methods"] = %w{GET POST PUT DELETE}.join(",")
headers["Access-Control-Allow-Headers"] = %w{Origin Accept Content-Type X-Requested-With X-CSRF-Token}.join(",")
head(:ok) if request.request_method == "OPTIONS"
end
Although Access-Control-Allow-Origin takes a wildcard, I highly recommend not using it as it opens up your app to all sorts of CSRF attacks. Using a whitelist is much better and more secure.
The Access-Control-Allow-Headers section is important, especially the X-Requested-With header. Rails doesn't like it if you send Ajax requests to it without this header, and ignores the request's Accept header, returning HTML when it should in fact return JSON.
It's worth noting that jQuery doesn't add this header to cross domain requests by default. This is an issue that Spine solves internally, but if you're using plain jQuery for CORs, you'll need to specify the header manually.
jQuery.ajaxSetup({
headers: {"X-Requested-With": "XMLHttpRequest"}
});
Some browsers send an options request to the server first, to make sure the correct access headers are set. You'll need to catch this in Rails, returning a 200 status with the correct headers. To do this, add the following to your application's config/routes.rb file:
match '*all' => 'application#cor', :constraints => {:method => 'OPTIONS'}
That's it, you're all set up for Cross Origin Requests with Spine!
I hacked rails to support the options method. I posted this on the rails list, but it never made it past the list.
GitHub Gist: Rails XHR2 / CORS / OPTIONS support
ctrl+f to find the lines that have #Options - those are the only ones I changed.
And here's an example implementation | and another

Resources