How to enable support for CORS with custom headers like authentication in Rails

I was building a client side application for my API that I built using Rails/Grape. So in order to access the resources using the API from the client application the first thing that I need to do was to enable CORS support in the API.

Enabling CORS using rack-cors gem

I did everything as was said in README, that is updated Gemfile accordingly and updated application.rb like this:

module YourApp
  class Application < Rails::Application

    # ...

    config.middleware.use Rack::Cors do
      allow do
        origins '*'
        resource '*', :headers => :any, :methods => [:get, :post, :options]
      end
    end

  end
end

It was pretty much straight forward, and now I have the CORS support enabled. My client side app should be able to access the API easily.

Problem: Custom Headers like Authorization.

Now that I had the CORS setup, I tried to authenticate the user using JWT, and the authorization header. I was stumped to see that the server is not returning the authorization headers.

After some dabbling with the code, I figured out that the authorization headers were not accessible only from another domain - Something wrong with the CORS setup.

Reason: Custom headers were not exposed by default with the rack-cors gem.

By default, the rack-cors gem only exposes certain values like Content-Type, Last-Modified etc.

So the authorization header that I was setting wasn't being exposed over to the cross-origin requests.

Expose custom headers.

To expose any custom headers, we need to explicitly specify the keys in our configuration.

config.middleware.use Rack::Cors do
      allow do
        origins '*'
        resource '*',
          :headers => :any,
          :expose  => ['access-token', 'expiry', 'token-type', 'Authorization'],
          :methods => [:get, :post, :options, :delete, :put]
      end
    end

So adding the expose key to the rack-cors configuration now exposes any custom headers like Authorization header