Skip to main content

Command Palette

Search for a command to run...

Rails `allowed_redirect_hosts` Finally Fixed Subdomain Redirects

Rails 8.1's allowed_redirect_hosts finally fixes the UnsafeRedirectError problem in multi-tenant apps

Updated
2 min read
A

Cofounder at Better Cater – building next-gen SaaS for caterers. Using Rails + AI to ship faster, fix pain points, and keep things simple.

The Problem Everyone Has

You're building a multi-tenant SaaS with subdomains. User logs in at www.myapp.com, you redirect them to tenant1.myapp.com. Rails throws this at you:

ActionController::Redirecting::UnsafeRedirectError:
Unsafe redirect to "http://tenant1.myapp.com"

Rails 7.0+ blocks cross-host redirects by default (good security!), but it treats your own subdomains as "external" hosts.

So what do you do?

What We've All Been Doing (It's Bad)

Option 1: Sprinkle allow_other_host: true everywhere

redirect_to root_url(subdomain: account.subdomain), allow_other_host: true

Problem: This allows redirects to any host, not just your subdomains. You're basically disabling the security feature you wanted.

Option 2: Monkey-patch Rails core

# config/initializers/url_host_allowed_patch.rb
module ActionController::Redirecting
  def _url_host_allowed?(url)
    # ... custom logic to check same base domain ...
  end
end

This is what we were doing. It works, but you're overriding Rails internals. It's fragile and breaks with updates.

The Fix (It's Stupidly Simple)

Rails merged PR #55420 in July 2025. Add this to your config:

# config/application.rb
config.action_controller.allowed_redirect_hosts = [".myapp.com"]

That's it. The dot prefix matches all subdomains: www.myapp.com, tenant1.myapp.com, api.myapp.com.

Now your redirects just work:

redirect_to root_url(subdomain: account.subdomain)  # Works!

No allow_other_host: true. No monkey-patches.

Pattern Matching You Get

The feature uses ActionDispatch::HostAuthorization::Permissions under the hood, which supports:

config.action_controller.allowed_redirect_hosts = [
  "api.myapp.com",           # Exact match
  ".myapp.com",              # All subdomains
  /.*\.staging\.myapp\.com/, # Regex patterns
  IPAddr.new("192.168.0.0/24") # IP ranges
]

For most multi-tenant apps, you just need the dot prefix.

I hope this helps, it's a brand new feature with almost no documentation yet, so I figured I'd share what I learned.