Skip to content

Commit

Permalink
Optionally allow ActionCable requests from the same host as origin
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
skateman committed Sep 21, 2016
1 parent 1996624 commit 268c340
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 1 deletion.
5 changes: 5 additions & 0 deletions actioncable/README.md
Expand Up @@ -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.
Expand Down
3 changes: 3 additions & 0 deletions actioncable/lib/action_cable/connection/base.rb
Expand Up @@ -195,8 +195,11 @@ def send_welcome_message
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
Expand Down
3 changes: 2 additions & 1 deletion actioncable/lib/action_cable/server/configuration.rb
Expand Up @@ -5,7 +5,7 @@ module Server
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
Expand All @@ -15,6 +15,7 @@ def initialize
@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.
Expand Down
8 changes: 8 additions & 0 deletions actioncable/test/connection/cross_site_forgery_test.rb
Expand Up @@ -18,6 +18,7 @@ def send_async(method, *args)
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
Expand Down Expand Up @@ -53,6 +54,13 @@ def send_async(method, *args)
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
Expand Down

0 comments on commit 268c340

Please sign in to comment.