Skip to content

REF-28: Verify the signature on incoming LogoutRequests - #95

Merged
thomasnymand merged 1 commit into
masterfrom
feature/REF-28-verify-logoutrequest-signature
Aug 26, 2026
Merged

thomasnymand merged 1 commit into
masterfrom
feature/REF-28-verify-logoutrequest-signature

Conversation

@thomasnymand

Copy link
Copy Markdown
Collaborator

Authenticates incoming LogoutRequests before the SP acts on them.

Problem

LogoutRequestService.validateLogoutRequest was an empty stub with no callers. LogoutRequestHandler decoded a LogoutRequest, looked up sessions by its SessionIndex, terminated them and invalidated the HTTP session, all without establishing that the message came from the IdP. The signature was logged, never verified, and the endpoint is reachable without a session.

Changes

  • validateLogoutRequest requires the request to be issued by the configured IdP and signed with its signing key from the configured metadata. handleGet and handleSOAP call it before any session state is read or changed.
  • Both signature forms are accepted: on the message itself (POST and SOAP), validated with SAMLSignatureProfileValidator followed by SignatureValidator; and on the query string (HTTP-Redirect binding), verified through OpenSAML's SAML2HTTPRedirectDeflateSignatureSecurityHandler with an ExplicitKeySignatureTrustEngine over the IdP metadata credential. A request carrying neither is rejected.
  • That handler no-ops when it does not handle a message, so the Signature parameter is required up front and SAMLPeerEntityContext.isAuthenticated() is asserted afterwards.

Verification

mvn -pl oiosaml test → 116 tests, 1 failure: the pre-existing OIOBPPUtilTest (JDK 26 JAXB incompatibility), which also fails on master.

New tests cover a request signed on the message, a request signed on the query string, and rejection of an unsigned request, one signed with an unknown key, and one from another issuer — each asserting that no session is touched. With the two production files reverted, all three rejection tests fail.

Two findings in the existing tests

  1. The test IdP issued LogoutRequests with the SP as Issuer, which is wrong for an IdP-initiated request and hid the missing issuer check. IdpUtil now issues them as the IdP and can sign them.
  2. Both SOAP tests embedded the message using StringUtil.elementToString, which sets INDENT=yes; pretty-printing a signed document breaks its digest. This was invisible while signatures were never verified. The tests now serialize the message unchanged. StringUtil.elementToString is only used for logging in production code, so there is no production impact.

Follow-up (not in this PR)

LogoutResponseService.validateLogoutResponse is likewise an empty stub that is never called, so a LogoutResponse status is acted on without verifying its signature or correlating InResponseTo. The trust engine and message-signature helpers added here are reusable for it.

LogoutRequestService.validateLogoutRequest was an empty stub with no callers, so
LogoutRequestHandler acted on LogoutRequests without authenticating them. The
signature was logged, never verified, and the endpoint is reachable without a
session.

validateLogoutRequest now requires the request to be issued by the configured
IdP and signed with its signing key from metadata, and handleGet and handleSOAP
call it before any session state is read or changed. Both signature forms are
accepted: on the message itself, as used for POST and SOAP, and on the query
string, as used by the HTTP-Redirect binding and verified through OpenSAMLs
SAML2HTTPRedirectDeflateSignatureSecurityHandler with a trust engine over the
IdP metadata credential. A request carrying neither is rejected.

Tests cover both signature forms, and the rejection of an unsigned request, one
signed with an unknown key and one from another issuer, each asserting that no
session is touched.

Test support: the test IdP issues LogoutRequests as the IdP rather than as the
SP and can sign them. Two SOAP tests serialized the signed message with the
pretty printing StringUtil.elementToString, which broke its signature.
@thomasnymand
thomasnymand merged commit 0b5b635 into master Aug 26, 2026
2 checks passed
@thomasnymand
thomasnymand deleted the feature/REF-28-verify-logoutrequest-signature branch August 26, 2026 15:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants