ruby-on-railsrack-cors

Rails - Allow localhost in CORS settings only in development


I'm configuring CORS settings for my rails server - I want to be able to test my backend when I run it locally, using a frontend on localhost.

But, to my understanding, CORS is an important security mechanism against CSRF(?), so when the app goes to production, I want the backend to only allow the origin of the live website. Like so:


if development:
  allow do
    origins 'localhost:3000', 'localhost:3001', 'https://my-app.com'

    resource '*',
      headers: :any,
      methods: [:get, :post, :put, :patch, :delete, :options, :head]
  end
end

if production:
  allow do
    origins 'https://my-app.com'

    resource '*',
      headers: :any,
      methods: [:get, :post, :put, :patch, :delete, :options, :head]
  end
end

I understand that it's quite a stretch to have an unknown user run a hostile app on localhost and not knowing what they're doing, but still, rather safe than sorry I'd say.

How would I go about this? And why is this not documented prominently on the Github page of Rack::CORS? I have a feeling there's something I'm missing. Please enlighten me.


Solution

  • If you're using Rails 5 or older you can handle the configuration when you are injecting the Rack::CORS middleware into the stack:

    # config/initializers/cors.rb
    Rails.application.config.middleware.insert_before 0, Rack::Cors do
      allow do
        if Rails.env.development?
          origins 'localhost:3000', 'localhost:3001', 'https://my-app.com'
        else
          origins 'https://my-app.com'
        end
    
        resource '*',
          headers: :any,
          methods: [:get, :post, :put, :patch, :delete, :options, :head]
      end
    end
    

    Since your Rails application is bootstrapped when initializers are loaded you can determine the environment through Rails.env. If you want to avoid hardcoding you could use an environmental variable.