aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDávid Halász <dhalasz@redhat.com>2016-09-21 14:55:25 +0200
committerDávid Halász <dhalasz@redhat.com>2016-09-21 16:10:46 +0200
commit268c340b0909bd78259e58b1ed0b53133d924199 (patch)
tree547d9bbf49af12fd29da581f3baa7cec8fa591e4
parent19966242163611e61d45ee4033f28aa6f967906a (diff)
downloadrails-268c340b0909bd78259e58b1ed0b53133d924199.tar.gz
rails-268c340b0909bd78259e58b1ed0b53133d924199.tar.bz2
rails-268c340b0909bd78259e58b1ed0b53133d924199.zip
Optionally allow ActionCable requests from the same host as origin
When the `allow_same_origin_as_host` is set to `true`, the request forgery protection permits `HTTP_ORIGIN` values starting with the corresponding `proto://` prefix followed by `HTTP_HOST`. This way it is not required to specify the list of allowed URLs.
-rw-r--r--actioncable/README.md5
-rw-r--r--actioncable/lib/action_cable/connection/base.rb3
-rw-r--r--actioncable/lib/action_cable/server/configuration.rb3
-rw-r--r--actioncable/test/connection/cross_site_forgery_test.rb8
4 files changed, 18 insertions, 1 deletions
diff --git a/actioncable/README.md b/actioncable/README.md
index 28e2602cbf..28a5d303fe 100644
--- a/actioncable/README.md
+++ b/actioncable/README.md
@@ -340,6 +340,11 @@ To disable and allow requests from any origin:
Rails.application.config.action_cable.disable_request_forgery_protection = true
```
+It is also possible to allow origins that are starting with the actual HTTP HOST header:
+```ruby
+Rails.application.config.action_cable.allow_same_origin_as_host = true
+```
+
### Consumer Configuration
Once you have decided how to run your cable server (see below), you must provide the server URL (or path) to your client-side setup.
diff --git a/actioncable/lib/action_cable/connection/base.rb b/actioncable/lib/action_cable/connection/base.rb
index 4c7fcc1434..76706a7465 100644
--- a/actioncable/lib/action_cable/connection/base.rb
+++ b/actioncable/lib/action_cable/connection/base.rb
@@ -195,8 +195,11 @@ module ActionCable
def allow_request_origin?
return true if server.config.disable_request_forgery_protection
+ proto = Rack::Request.new(env).ssl? ? "https" : "http"
if Array(server.config.allowed_request_origins).any? { |allowed_origin| allowed_origin === env["HTTP_ORIGIN"] }
true
+ elsif server.config.allow_same_origin_as_host && env["HTTP_ORIGIN"] == "#{proto}://#{env['HTTP_HOST']}"
+ true
else
logger.error("Request origin not allowed: #{env['HTTP_ORIGIN']}")
false
diff --git a/actioncable/lib/action_cable/server/configuration.rb b/actioncable/lib/action_cable/server/configuration.rb
index 7153593d4c..4286fe5f0d 100644
--- a/actioncable/lib/action_cable/server/configuration.rb
+++ b/actioncable/lib/action_cable/server/configuration.rb
@@ -5,7 +5,7 @@ module ActionCable
class Configuration
attr_accessor :logger, :log_tags
attr_accessor :use_faye, :connection_class, :worker_pool_size
- attr_accessor :disable_request_forgery_protection, :allowed_request_origins
+ attr_accessor :disable_request_forgery_protection, :allowed_request_origins, :allow_same_origin_as_host
attr_accessor :cable, :url, :mount_path
def initialize
@@ -15,6 +15,7 @@ module ActionCable
@worker_pool_size = 4
@disable_request_forgery_protection = false
+ @allow_same_origin_as_host = false
end
# Returns constant of subscription adapter specified in config/cable.yml.
diff --git a/actioncable/test/connection/cross_site_forgery_test.rb b/actioncable/test/connection/cross_site_forgery_test.rb
index 3bc59c9db9..6cabff5440 100644
--- a/actioncable/test/connection/cross_site_forgery_test.rb
+++ b/actioncable/test/connection/cross_site_forgery_test.rb
@@ -18,6 +18,7 @@ class ActionCable::Connection::CrossSiteForgeryTest < ActionCable::TestCase
teardown do
@server.config.disable_request_forgery_protection = false
@server.config.allowed_request_origins = []
+ @server.config.allow_same_origin_as_host = false
end
test "disable forgery protection" do
@@ -53,6 +54,13 @@ class ActionCable::Connection::CrossSiteForgeryTest < ActionCable::TestCase
assert_origin_not_allowed "http://rails.co.uk"
end
+ test "allow same origin as host" do
+ @server.config.allow_same_origin_as_host = true
+ assert_origin_allowed "http://#{HOST}"
+ assert_origin_not_allowed "http://hax.com"
+ assert_origin_not_allowed "http://rails.co.uk"
+ end
+
private
def assert_origin_allowed(origin)
response = connect_with_origin origin