Skip to content

Commit c52cc1e

Browse files
committed
gate controller patch and view override on model devise modules
Check if the AdminUser model includes :omniauthable before registering the omniauth_callbacks controller or prepending the SSO login view. This makes the gem a no-op when OIDC is not enabled on the model, so host apps can keep the gem in the Gemfile while toggling OIDC on/off via concern inclusion without needing routes workarounds.
1 parent 1f80549 commit c52cc1e

File tree

1 file changed

+21
-37
lines changed

1 file changed

+21
-37
lines changed

lib/activeadmin/oidc/engine.rb

Lines changed: 21 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,30 @@
44

55
module ActiveAdmin
66
module Oidc
7-
# Mountable Rails engine. Ships the OmniauthCallbacksController the host
8-
# app's Devise setup routes to, and exposes the hardcoded callback path
9-
# all hosts share.
107
class Engine < ::Rails::Engine
11-
# OmniAuth strategy name. The callback URL in the host app is
12-
# <host>/admin/auth/oidc/callback
13-
# (ActiveAdmin mounts Devise under /admin by default.) Zitadel and
14-
# other IdPs support multiple redirect URIs per app, so hardcoding
15-
# this path keeps config surface small with no real downside.
168
PROVIDER_NAME = :oidc
179

18-
# Prepended into ActiveAdmin::Devise's singleton class so that
19-
# `ActiveAdmin::Devise.controllers` includes the gem's omniauth
20-
# callbacks controller without any host-app wiring.
10+
# True when the host's AdminUser model includes :omniauthable.
11+
# Used to gate controller registration and view overrides so the
12+
# gem is a no-op when OIDC is not enabled on the model.
13+
def self.oidc_enabled?
14+
admin_class = ActiveAdmin::Oidc.config.admin_user_class
15+
klass = admin_class.is_a?(String) ? admin_class.safe_constantize : admin_class
16+
klass&.respond_to?(:devise_modules) && klass.devise_modules.include?(:omniauthable)
17+
end
18+
2119
ControllersPatch = Module.new do
2220
def controllers
23-
super.merge(
24-
omniauth_callbacks: "active_admin/oidc/devise/omniauth_callbacks"
25-
)
21+
result = super
22+
if Engine.oidc_enabled?
23+
result = result.merge(
24+
omniauth_callbacks: "active_admin/oidc/devise/omniauth_callbacks"
25+
)
26+
end
27+
result
2628
end
2729
end
2830

29-
# Apply the patch once ActiveAdmin::Devise is loadable. We use
30-
# `to_prepare` rather than a regular initializer because
31-
# `active_admin/devise` references `::Devise::SessionsController`
32-
# at file load, and that constant isn't autoloadable until
33-
# ActionDispatch has set up controller autoload paths — which
34-
# only happens after the initializer phase.
3531
initializer "activeadmin_oidc.register_controllers" do |app|
3632
app.config.to_prepare do
3733
require "active_admin/devise"
@@ -41,28 +37,16 @@ def controllers
4137
end
4238
end
4339

44-
# Make sure the gem's login view override wins over ActiveAdmin's
45-
# default. ActiveAdmin's view path is registered when its engine
46-
# initializes; we prepend ours in `to_prepare` so it lands in front
47-
# of ActiveAdmin's Devise::SessionsController view lookup.
4840
initializer "activeadmin_oidc.prepend_view_paths" do |app|
4941
app.config.to_prepare do
50-
require "active_admin/devise"
51-
view_path = File.expand_path("../../../app/views", __dir__)
52-
::ActiveAdmin::Devise::SessionsController.prepend_view_path(view_path)
42+
if Engine.oidc_enabled?
43+
require "active_admin/devise"
44+
view_path = File.expand_path("../../../app/views", __dir__)
45+
::ActiveAdmin::Devise::SessionsController.prepend_view_path(view_path)
46+
end
5347
end
5448
end
5549

56-
# Prevent OAuth codes, tokens and CSRF/replay guards from ever
57-
# landing in Rails logs. If the host app crashes mid-callback
58-
# Rails will dump the full params hash into the log; we merge
59-
# the known-sensitive keys into `filter_parameters` so they
60-
# come out as [FILTERED]. The host app's own filter_parameters
61-
# are preserved — we only add.
62-
#
63-
# `state` and `nonce` aren't "secret" in the strong sense, but
64-
# they're single-use session-bound values and treating them as
65-
# opaque in logs is the industry default.
6650
initializer "activeadmin_oidc.filter_parameters" do |app|
6751
app.config.filter_parameters |= %i[code id_token access_token refresh_token state nonce]
6852
end

0 commit comments

Comments
 (0)