Class: LcpRuby::Auth::SessionsController

Inherits:
Devise::SessionsController
  • Object
show all
Includes:
BaseController
Defined in:
app/controllers/lcp_ruby/auth/sessions_controller.rb

Instance Method Summary collapse

Instance Method Details

#createObject



27
28
29
30
31
32
33
34
# File 'app/controllers/lcp_ruby/auth/sessions_controller.rb', line 27

def create
  unless LcpRuby::Authentication::ProviderRegistry.
    flash[:alert] = I18n.t("lcp_ruby.auth.password_disabled",
                           default: "Password sign-in is disabled.")
    redirect_to(new_user_session_path) and return
  end
  super
end

#destroyObject

Devise destroy + optional RP-initiated OIDC logout. When the signed-in user came in via an OIDC provider configured with logout.mode: rp_initiated, redirect after local sign-out to the IdP’s end_session_endpoint with id_token_hint and post_logout_redirect_uri, so the user is also signed out of the IdP for this RP.

The RP-initiated branch must run BEFORE ‘super` because Devise’s destroy ends in ‘respond_to_on_destroy`, which calls `redirect_to after_sign_out_path_for(…)` and sets `response_body`. A second `redirect_to` after super would raise AbstractController::DoubleRenderError.



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'app/controllers/lcp_ruby/auth/sessions_controller.rb', line 46

def destroy
  # Read the user directly from Warden's session store. This is the correct
  # API for "what user is in this session right now" — we don't need to run
  # full authentication strategies (timeoutable, lockable, …) just to figure
  # out where to redirect. Using `current_user` here would also be fragile:
  # host apps can override `ApplicationController#current_user`, and in
  # test rigs (spec/dummy) that override may shadow Devise's helper entirely.
  oidc_user     = request.env["warden"]&.user(:user)
  provider_name = oidc_user && oidc_user.respond_to?(:provider) ? oidc_user.provider.presence : nil
  provider      = provider_name && LcpRuby::Authentication::ProviderRegistry.find_by(provider_name)
  id_token      = session[:oidc_id_token]

  if provider&.oidc? && provider.logout[:mode] == :rp_initiated
    end_session_url = build_end_session_url(provider, id_token)
    if end_session_url
      Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name)
      flash[:notice] = I18n.t("lcp_ruby.auth.signed_out", default: "You have been signed out.")
      redirect_to(end_session_url, allow_other_host: true) and return
    end

    # end_session_endpoint missing or discovery unavailable — fall through
    # to local-only sign-out so the user isn't trapped half-signed-in.
    Rails.logger.info(
      "[lcp_ruby] OIDC end_session_endpoint unavailable for provider=#{provider.name}; " \
      "completing local sign-out only."
    )
  end

  super
  flash[:notice] ||= I18n.t("lcp_ruby.auth.signed_out", default: "You have been signed out.")
end

#newObject



16
17
18
19
20
21
22
23
24
25
# File 'app/controllers/lcp_ruby/auth/sessions_controller.rb', line 16

def new
  registry = LcpRuby::Authentication::ProviderRegistry
  @providers          = registry.all
  @oidc_providers     = registry.oidc_providers
  @show_password_form = registry.
  @auto_redirect      = @oidc_providers.size == 1 &&
                        !@show_password_form &&
                        registry.default_auto_redirect?
  super
end