Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,18 @@ def after_sign_in_path_for(resource)
stored_location_for(resource) || '/admin'
end

# Devise's default `after_omniauth_failure_path_for` calls
# `new_session_path(scope)`, a URL helper Devise only generates
# when :database_authenticatable mounts session routes. The
# engine mounts `new_<scope>_session_path` itself (see
# `mount_oidc_sessions_routes` initializer) regardless of which
# modules are loaded, so we always route through that helper.
# Devise's `new_session_path(scope)` is only generated when
# `:database_authenticatable` is in the mapping's `used_helpers`,
# so an OIDC-only model never gets it. The engine mounts
# `new_<scope>_session_path` itself, but the helper lives on
# whichever route set the mapping's `router_name` points at —
# main_app by default, or `<engine_name>` for hosts that mount
# Devise inside a Rails engine. Replicate Devise's own dispatch
# so the right context is asked.
def after_omniauth_failure_path_for(scope)
public_send(:"new_#{scope}_session_path")
router_name = ::Devise.mappings[scope].router_name
context = router_name ? send(router_name) : self
context.public_send(:"new_#{scope}_session_path")
end
end
end
Expand Down
19 changes: 19 additions & 0 deletions spec/engine/features/engine_mounted_login_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,23 @@
visit "/admin"
expect(page).to have_current_path("/admin/login")
end

context "OmniAuth failure path" do
around do |ex|
saved = OmniAuth.config.mock_auth[:oidc]
OmniAuth.config.mock_auth[:oidc] = :invalid_credentials
ex.run
OmniAuth.config.mock_auth[:oidc] = saved
end

scenario "failed OmniAuth callback lands back on the SSO landing page" do
# OmniauthCallbacksController#after_omniauth_failure_path_for has
# to resolve `new_<scope>_session_path` against the engine's
# route set (Devise.router_name pins helpers there) — calling the
# helper directly on the controller would raise NoMethodError.
visit "/admin/login"
click_button ActiveAdmin::Oidc.config.login_button_label
expect(page).to have_current_path("/admin/login")
end
end
end
19 changes: 19 additions & 0 deletions spec/isolated/features/isolated_engine_login_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,23 @@
expect(page.status_code).to eq(200)
expect(page.body).to include(ActiveAdmin::Oidc.config.login_button_label)
end

context "OmniAuth failure path" do
around do |ex|
saved = OmniAuth.config.mock_auth[:oidc]
OmniAuth.config.mock_auth[:oidc] = :invalid_credentials
ex.run
OmniAuth.config.mock_auth[:oidc] = saved
end

scenario "failed OmniAuth callback lands back on the SSO landing page" do
# As in the non-isolated case, the failure handler must resolve
# the session helper through the engine — and via the isolated
# engine's mount prefix the effective path stays `/admin/login`
# because `config.login_path = '/login'` is engine-relative.
visit "/admin/login"
click_button ActiveAdmin::Oidc.config.login_button_label
expect(page).to have_current_path("/admin/login")
end
end
end
Loading