From 25d63167c83fd5e8adef91b8f1b21a7e6763c011 Mon Sep 17 00:00:00 2001 From: Martin Voigt Date: Thu, 6 Aug 2026 15:52:52 +0200 Subject: [PATCH 1/6] Support extra_redirect_uris to support login providers for spaces that are not a subdomain of the default space --- app/helpers/application_helper.rb | 15 +++++----- app/helpers/spaces_helper.rb | 17 ++++++++++- .../sessions/_omniauth_options.html.erb | 10 +++---- app/views/devise/sessions/new.html.erb | 2 +- app/views/layouts/_login_menu.html.erb | 6 ++-- config/initializers/omniauth.rb | 2 ++ config/initializers/omniauth/ls_login.rb | 7 ++++- config/initializers/omniauth/oidc.rb | 9 ++++-- config/initializers/omniauth/oidc2.rb | 9 ++++-- config/secrets.example.yml | 6 ++++ config/secrets.github.yml | 4 +++ .../host_redirect_openid_connect.rb | 26 +++++++++++++++++ test/integration/login_test.rb | 29 +++++++++++++++++++ 13 files changed, 117 insertions(+), 25 deletions(-) create mode 100644 lib/omniauth/strategies/host_redirect_openid_connect.rb diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index e5f9ca7c1..f390e6f15 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -705,15 +705,14 @@ def theme_path "themes/#{params[:theme_preview] || current_space&.theme || TeSS::Config.site['default_theme'] || 'default'}" end - def omniauth_login_link(provider, config) + def omniauth_login_link(provider, config, html_options = {}) params = Space.current_space&.default? ? {} : { space_id: Space.current_space.id } - link_to( - t('authentication.omniauth.log_in_with', - provider: config.options[:label] || - t("authentication.omniauth.providers.#{provider}", default: provider.to_s.titleize)), - omniauth_authorize_path('user', provider, **params), - method: :post - ) + label = t('authentication.omniauth.log_in_with', + provider: config.options[:label] || + t("authentication.omniauth.providers.#{provider}", default: provider.to_s.titleize)) + + link_to(capture { block_given? ? yield : label }, omniauth_authorize_path('user', provider, **params), + { method: :post }.merge(html_options)) end def per_page_options_for_select diff --git a/app/helpers/spaces_helper.rb b/app/helpers/spaces_helper.rb index 5bc7dd50c..b6827a2ba 100644 --- a/app/helpers/spaces_helper.rb +++ b/app/helpers/spaces_helper.rb @@ -20,7 +20,22 @@ def space_feature_options end end + def omniauth_providers_for_space(space = current_space) + host = space&.host || TeSS::Config.base_uri.host + + Devise.omniauth_configs.select do |_provider, config| + default_redirect_uri = config.options.dig(:client_options, :redirect_uri) + extra_redirect_uris = Array(config.options[:extra_redirect_uris]) + + [default_redirect_uri, *extra_redirect_uris].compact_blank.any? do |uri| + URI.parse(uri).host == host + rescue URI::InvalidURIError + false + end + end + end + def space_supports_omniauth?(space = current_space) - space.nil? || space.default? || space.is_subdomain?(TeSS::Config.base_uri.domain) + omniauth_providers_for_space(space).any? end end diff --git a/app/views/devise/sessions/_omniauth_options.html.erb b/app/views/devise/sessions/_omniauth_options.html.erb index 68745c4c7..b7d48974c 100644 --- a/app/views/devise/sessions/_omniauth_options.html.erb +++ b/app/views/devise/sessions/_omniauth_options.html.erb @@ -1,14 +1,14 @@ <% if devise_mapping.omniauthable? -%> - <% Devise.omniauth_configs.each do |provider, config| -%> - <%= link_to(omniauth_authorize_path(resource_name, provider), method: :post, - class: config.options[:logo] ? '' : - TeSS::Config.feature["login_through_oidc_only"] ? 'btn btn-default btn-lg btn-oidc-only' : 'btn btn-default') do %> + <% omniauth_providers_for_space.each do |provider, config| -%> + <%= omniauth_login_link(provider, config, + class: config.options[:logo] ? '' : + TeSS::Config.feature["login_through_oidc_only"] ? 'btn btn-default btn-lg btn-oidc-only' : 'btn btn-default') do %> <% if config.options[:logo].present? %> <%= image_tag(config.options[:logo], class: "omniauth-logo omniauth-#{provider}") -%> <% else %> <%= t('authentication.omniauth.log_in_with', provider: config.options[:label] || t("authentication.omniauth.providers.#{provider}", default: provider.to_s.titleize)) -%> <% end %> - <% end -%> + <% end %> <% end -%> <% end -%> diff --git a/app/views/devise/sessions/new.html.erb b/app/views/devise/sessions/new.html.erb index a8518c381..47a6a9aa0 100644 --- a/app/views/devise/sessions/new.html.erb +++ b/app/views/devise/sessions/new.html.erb @@ -5,7 +5,7 @@ <% end %>
- <% if resource_class.omniauth_providers.any? && devise_mapping.omniauthable? %> + <% if space_supports_omniauth? && devise_mapping.omniauthable? %>
<%= t('authentication.omniauth.title') %>

<%= t('authentication.omniauth.description') %>

<%= render partial: 'devise/sessions/omniauth_options' %> diff --git a/app/views/layouts/_login_menu.html.erb b/app/views/layouts/_login_menu.html.erb index f216f5b2e..a5ef4630e 100644 --- a/app/views/layouts/_login_menu.html.erb +++ b/app/views/layouts/_login_menu.html.erb @@ -1,6 +1,6 @@ -<% if TeSS::Config.feature["login_through_oidc_only"] && Devise.omniauth_configs.size == 1 %> +<% if TeSS::Config.feature["login_through_oidc_only"] && omniauth_providers_for_space.size == 1 %>
  • - <% provider, config = Devise.omniauth_configs.first %> + <% provider, config = omniauth_providers_for_space.first %> <%= omniauth_login_link(provider, config) %>
  • <% else %> @@ -10,7 +10,7 @@