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

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

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.

How to set swagger UI to be able use Try It Out with Authentication?

I am trying ot find a way how to setup properly Swagger UI to be able use Try It Out functionality with Authentication. I have API whith Basic HTTP Authentication which is crucial for business.
Unfortunately Swagger UI sends only OPTIONS requests without Basic HTTP header.
I found some articles on internet but almost all are saying that OPTIONS doesn't contain the header.
Is it there any way how to force Swagger UI use POST including the Authorization header instead of OPTIONS without the header?
Request URL:https://blabla.blabla.com/rest/blabla/ShipmentRequest
Request Method:OPTIONS
Status Code:401 Unauthorized
Remote Address:001.02.003.004:443
Referrer Policy:no-referrer-when-downgrade
Thank you, Reddy

AngularJS and rails cors headers not working

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.

Do Ruby on Rails 3 Jquery AJAX POST requests need the authenticity_token?

According to the Rails security guide, if you use protect_from_forgery, all non-GET requests include an authenticity token. When I have Jquery AJAX POST requests, however, I don't see the authenticity_token param as one of the params in the request. Is this how it's supposed to work?
Also, it seems that POST requests from outside a session (curl in a script) don't require an authencity_token, either.
Thanks!
Rails will send this parameter in the headers rather than in the post data. You need to include the built in rails UJS library to get this to work. Take a look at the headers in your request and you should see one called X-CSRF-Token.

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