logout.rb 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. # Copyright (C) 2012-2025 Zammad Foundation, https://zammad-foundation.org/
  2. module Gql::Mutations
  3. class Logout < BaseMutation
  4. include Gql::Mutations::Concerns::Logout::HandlesOidcAuthorization
  5. description 'End the current session'
  6. field :success, Boolean, null: false, description: 'Was the logout successful?'
  7. field :external_logout_url, String, null: true, description: 'External logout URL (e.g. for SAML)?'
  8. # Don't require an authenticated user, because that is not present in maintenance_mode,
  9. # when users still need to be correctly logged out.
  10. def self.authorize(...)
  11. true
  12. end
  13. def self.requires_csrf_verification?
  14. false
  15. end
  16. def resolve(...)
  17. # Handling of third-party logouts (we need to redirect to the IDP).
  18. return saml_destroy if saml_session?
  19. return oidc_destroy if oidc_session?
  20. context[:controller].reset_session
  21. context[:current_user] = nil
  22. context[:controller].request.env['rack.session.options'][:expire_after] = nil
  23. { success: true }
  24. end
  25. def saml_destroy
  26. { success: true, external_logout_url: saml_logout_url }
  27. rescue => e
  28. Rails.logger.error "SAML SLO failed: #{e.message}"
  29. end
  30. def saml_session?
  31. (session['saml_uid'] || session['saml_session_index']) && OmniAuth::Strategies::SamlDatabase.setup.fetch('idp_slo_service_url', nil)
  32. end
  33. def saml_logout_url
  34. options = OmniAuth::Strategies::SamlDatabase.setup
  35. settings = OneLogin::RubySaml::Settings.new(options)
  36. logout_request = OneLogin::RubySaml::Logoutrequest.new
  37. # Since we created a new SAML request, save the transaction_id
  38. # to compare it with the response we get back
  39. session['saml_transaction_id'] = logout_request.uuid
  40. settings.name_identifier_value = session['saml_uid']
  41. settings.sessionindex = session['saml_session_index']
  42. saml_remember_origin
  43. logout_request.create(settings)
  44. end
  45. def saml_remember_origin
  46. session['omniauth.origin'] = context[:controller].request.env['HTTP_REFERER']
  47. end
  48. def session
  49. @session ||= context[:controller].session
  50. end
  51. end
  52. end