Files
pulse/internal
rcourtman 0ac04c8d39 Validate SAML LogoutResponse before clearing session
handleSAMLSLO was an unauthenticated force-logout DoS: any cross-origin
GET or POST to /api/saml/{id}/slo cleared the user's session and
returned a 302 to /?logout=success. No SAML payload was required, no
signature validation, no IdP-identity check.

Add ValidateLogoutResponse to SAMLService wrapping crewjam/saml's
ServiceProvider.ValidateLogoutResponseRequest, which validates the
XML-DSig against the configured IdP certificate and the standard
LogoutResponse temporal and target invariants.

In handleSAMLSLO:
  - extract and validate the provider ID
  - require either a SAMLResponse (response to our SLO request) or a
    SAMLRequest (IdP-initiated SLO) parameter — reject bare requests
    with 400 and do not clear session
  - reject IdP-initiated LogoutRequest with 400: we don't track
    in-flight request IDs to bind one to yet, and silently treating it
    as a force-logout signal is the same bug we are closing
  - on SAMLResponse, call service.ValidateLogoutResponse. On failure
    return 403 and do not clear session; audit-log the failure
  - only when validation passes do we clear the session and redirect

Regression tests:
  - TestHandleSAMLSLO_RejectsEmptyPayload (400, no redirect, no session
    state mutation)
  - TestHandleSAMLSLO_RejectsInvalidLogoutResponse (403 on garbage
    SAMLResponse value)
  - TestHandleSAMLSLO_RejectsIDPInitiatedLogoutRequest (400 on
    SAMLRequest-only payload)

The prior TestHandleSAMLSLO_Redirects test, which asserted the unsafe
"clear session and 302 on any GET" behaviour, is replaced by the
three above.
2026-05-21 16:15:53 +01:00
..
2026-05-21 00:59:00 +01:00