REF-28: Verify the signature on incoming LogoutRequests - #95
Merged
thomasnymand merged 1 commit intoAug 26, 2026
Merged
Conversation
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.
mthiim
approved these changes
Aug 26, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Authenticates incoming LogoutRequests before the SP acts on them.
Problem
LogoutRequestService.validateLogoutRequestwas an empty stub with no callers.LogoutRequestHandlerdecoded a LogoutRequest, looked up sessions by itsSessionIndex, 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
validateLogoutRequestrequires the request to be issued by the configured IdP and signed with its signing key from the configured metadata.handleGetandhandleSOAPcall it before any session state is read or changed.SAMLSignatureProfileValidatorfollowed bySignatureValidator; and on the query string (HTTP-Redirect binding), verified through OpenSAML'sSAML2HTTPRedirectDeflateSignatureSecurityHandlerwith anExplicitKeySignatureTrustEngineover the IdP metadata credential. A request carrying neither is rejected.Signatureparameter is required up front andSAMLPeerEntityContext.isAuthenticated()is asserted afterwards.Verification
mvn -pl oiosaml test→ 116 tests, 1 failure: the pre-existingOIOBPPUtilTest(JDK 26 JAXB incompatibility), which also fails onmaster.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
Issuer, which is wrong for an IdP-initiated request and hid the missing issuer check.IdpUtilnow issues them as the IdP and can sign them.StringUtil.elementToString, which setsINDENT=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.elementToStringis only used for logging in production code, so there is no production impact.Follow-up (not in this PR)
LogoutResponseService.validateLogoutResponseis likewise an empty stub that is never called, so a LogoutResponse status is acted on without verifying its signature or correlatingInResponseTo. The trust engine and message-signature helpers added here are reusable for it.