Separate Forward auth into it's own models + controller
Some checks failed
CI / scan_ruby (push) Has been cancelled
CI / scan_js (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / test (push) Has been cancelled
CI / system-test (push) Has been cancelled

This commit is contained in:
Dan Milne
2025-10-24 10:56:27 +11:00
parent ee4af20000
commit fc9afcd1b7
20 changed files with 696 additions and 16 deletions

View File

@@ -41,7 +41,21 @@ module Authentication
def start_new_session_for(user)
user.sessions.create!(user_agent: request.user_agent, ip_address: request.remote_ip).tap do |session|
Current.session = session
cookies.signed.permanent[:session_id] = { value: session.id, httponly: true, same_site: :lax }
# Extract root domain for cross-subdomain cookies (required for forward auth)
domain = extract_root_domain(request.host)
cookie_options = {
value: session.id,
httponly: true,
same_site: :lax,
secure: Rails.env.production?
}
# Set domain for cross-subdomain authentication if we can extract it
cookie_options[:domain] = domain if domain.present?
cookies.signed.permanent[:session_id] = cookie_options
end
end
@@ -49,4 +63,37 @@ module Authentication
Current.session.destroy
cookies.delete(:session_id)
end
# Extract root domain for cross-subdomain cookies
# Examples:
# - clinch.aapamilne.com -> .aapamilne.com
# - app.example.co.uk -> .example.co.uk
# - localhost -> nil (no domain setting for local development)
def extract_root_domain(host)
return nil if host.blank? || host.match?(/^(localhost|127\.0\.0\.1|::1)$/)
# Split hostname into parts
parts = host.split('.')
# For normal domains like example.com, we need at least 2 parts
# For complex domains like co.uk, we need at least 3 parts
return nil if parts.length < 2
# Extract root domain with leading dot for cross-subdomain cookies
if parts.length >= 3
# Check if it's a known complex TLD
complex_tlds = %w[co.uk com.au co.nz co.za co.jp]
second_level = "#{parts[-2]}.#{parts[-1]}"
if complex_tlds.include?(second_level)
# For complex TLDs, include more parts: app.example.co.uk -> .example.co.uk
root_parts = parts[-3..-1]
return ".#{root_parts.join('.')}"
end
end
# For regular domains: app.example.com -> .example.com
root_parts = parts[-2..-1]
".#{root_parts.join('.')}"
end
end