44
55module 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