101 lines
4.1 KiB
Ruby
101 lines
4.1 KiB
Ruby
class ActiveSessionsController < ApplicationController
|
|
def show
|
|
@user = Current.session.user
|
|
@active_sessions = @user.sessions.active.order(last_activity_at: :desc)
|
|
@connected_applications = @user.oidc_user_consents.includes(:application).order(granted_at: :desc)
|
|
end
|
|
|
|
def revoke_consent
|
|
@user = Current.session.user
|
|
application = Application.find(params[:application_id])
|
|
|
|
# Check if user has consent for this application
|
|
consent = @user.oidc_user_consents.find_by(application: application)
|
|
unless consent
|
|
redirect_to active_sessions_path, alert: "No consent found for this application."
|
|
return
|
|
end
|
|
|
|
# Send backchannel logout notification before revoking consent
|
|
if application.supports_backchannel_logout?
|
|
BackchannelLogoutJob.perform_later(
|
|
user_id: @user.id,
|
|
application_id: application.id,
|
|
consent_sid: consent.sid
|
|
)
|
|
Rails.logger.info "ActiveSessionsController: Enqueued backchannel logout for #{application.name}"
|
|
end
|
|
|
|
# Revoke all tokens for this user-application pair
|
|
now = Time.current
|
|
revoked_access_tokens = OidcAccessToken.where(application: application, user: @user, revoked_at: nil)
|
|
.update_all(revoked_at: now)
|
|
revoked_refresh_tokens = OidcRefreshToken.where(application: application, user: @user, revoked_at: nil)
|
|
.update_all(revoked_at: now)
|
|
|
|
Rails.logger.info "ActiveSessionsController: Revoked #{revoked_access_tokens} access tokens and #{revoked_refresh_tokens} refresh tokens for #{application.name}"
|
|
|
|
# Revoke the consent
|
|
consent.destroy
|
|
redirect_to active_sessions_path, notice: "Successfully revoked access to #{application.name}."
|
|
end
|
|
|
|
def logout_from_app
|
|
@user = Current.session.user
|
|
application = Application.find(params[:application_id])
|
|
|
|
# Check if user has consent for this application
|
|
consent = @user.oidc_user_consents.find_by(application: application)
|
|
unless consent
|
|
redirect_to root_path, alert: "No active session found for this application."
|
|
return
|
|
end
|
|
|
|
# Send backchannel logout notification
|
|
if application.supports_backchannel_logout?
|
|
BackchannelLogoutJob.perform_later(
|
|
user_id: @user.id,
|
|
application_id: application.id,
|
|
consent_sid: consent.sid
|
|
)
|
|
Rails.logger.info "ActiveSessionsController: Enqueued backchannel logout for #{application.name}"
|
|
end
|
|
|
|
# Revoke all tokens for this user-application pair
|
|
now = Time.current
|
|
revoked_access_tokens = OidcAccessToken.where(application: application, user: @user, revoked_at: nil)
|
|
.update_all(revoked_at: now)
|
|
revoked_refresh_tokens = OidcRefreshToken.where(application: application, user: @user, revoked_at: nil)
|
|
.update_all(revoked_at: now)
|
|
|
|
Rails.logger.info "ActiveSessionsController: Logged out from #{application.name} - revoked #{revoked_access_tokens} access tokens and #{revoked_refresh_tokens} refresh tokens"
|
|
|
|
# Keep the consent intact - this is the key difference from revoke_consent
|
|
redirect_to root_path, notice: "Successfully logged out of #{application.name}."
|
|
end
|
|
|
|
def revoke_all_consents
|
|
@user = Current.session.user
|
|
consents = @user.oidc_user_consents.includes(:application)
|
|
count = consents.count
|
|
|
|
if count > 0
|
|
# Send backchannel logout notifications before revoking consents
|
|
consents.each do |consent|
|
|
next unless consent.application.supports_backchannel_logout?
|
|
|
|
BackchannelLogoutJob.perform_later(
|
|
user_id: @user.id,
|
|
application_id: consent.application.id,
|
|
consent_sid: consent.sid
|
|
)
|
|
end
|
|
Rails.logger.info "ActiveSessionsController: Enqueued #{count} backchannel logout notifications"
|
|
|
|
@user.oidc_user_consents.destroy_all
|
|
redirect_to active_sessions_path, notice: "Successfully revoked access to #{count} applications."
|
|
else
|
|
redirect_to active_sessions_path, alert: "No applications to revoke."
|
|
end
|
|
end
|
|
end |