Addressed review comments

Signed-off-by: Liviu Gheorghe <liviu.gheorghe.ro@gmail.com>
This commit is contained in:
1livv 2025-06-07 16:43:12 +03:00 committed by Liviu Gheorghe
parent ce6f66e915
commit fc1b509853
8 changed files with 59 additions and 84 deletions

View File

@ -371,7 +371,7 @@ public class Saml2LogoutConfigurerTests {
} }
@Test @Test
public void saml2LogoutRequestWhenNoRegistrationThen401() throws Exception { public void saml2LogoutRequestWhenNoRegistrationThen400() throws Exception {
this.spring.register(Saml2LogoutDefaultsConfig.class).autowire(); this.spring.register(Saml2LogoutDefaultsConfig.class).autowire();
DefaultSaml2AuthenticatedPrincipal principal = new DefaultSaml2AuthenticatedPrincipal("user", DefaultSaml2AuthenticatedPrincipal principal = new DefaultSaml2AuthenticatedPrincipal("user",
Collections.emptyMap()); Collections.emptyMap());
@ -384,7 +384,7 @@ public class Saml2LogoutConfigurerTests {
.param("SigAlg", this.apLogoutRequestSigAlg) .param("SigAlg", this.apLogoutRequestSigAlg)
.param("Signature", this.apLogoutRequestSignature) .param("Signature", this.apLogoutRequestSignature)
.with(authentication(user))) .with(authentication(user)))
.andExpect(status().isUnauthorized()); .andExpect(status().isBadRequest());
verifyNoInteractions(getBean(LogoutHandler.class)); verifyNoInteractions(getBean(LogoutHandler.class));
} }

View File

@ -271,7 +271,7 @@ public class Saml2LogoutBeanDefinitionParserTests {
} }
@Test @Test
public void saml2LogoutRequestWhenNoRegistrationThen401() throws Exception { public void saml2LogoutRequestWhenNoRegistrationThen400() throws Exception {
this.spring.configLocations(this.xml("Default")).autowire(); this.spring.configLocations(this.xml("Default")).autowire();
DefaultSaml2AuthenticatedPrincipal principal = new DefaultSaml2AuthenticatedPrincipal("user", DefaultSaml2AuthenticatedPrincipal principal = new DefaultSaml2AuthenticatedPrincipal("user",
Collections.emptyMap()); Collections.emptyMap());
@ -284,7 +284,7 @@ public class Saml2LogoutBeanDefinitionParserTests {
.param("SigAlg", this.apLogoutRequestSigAlg) .param("SigAlg", this.apLogoutRequestSigAlg)
.param("Signature", this.apLogoutRequestSignature) .param("Signature", this.apLogoutRequestSignature)
.with(authentication(user))) .with(authentication(user)))
.andExpect(status().isUnauthorized()); .andExpect(status().isBadRequest());
} }
@Test @Test

View File

@ -130,30 +130,6 @@ public final class Saml2ErrorCodes {
*/ */
public static final String INVALID_IN_RESPONSE_TO = "invalid_in_response_to"; public static final String INVALID_IN_RESPONSE_TO = "invalid_in_response_to";
/**
* The RP registration does not have configured a logout request endpoint
* @since 6.3
*/
public static final String MISSING_LOGOUT_REQUEST_ENDPOINT = "missing_logout_request_endpoint";
/**
* The saml response or logout request was delivered via an invalid binding
* @since 6.3
*/
public static final String INVALID_BINDING = "invalid_binding";
/**
* The saml logout request failed validation
* @since 6.3
*/
public static final String INVALID_LOGOUT_REQUEST = "invalid_logout_request";
/**
* The saml logout response could not be generated
* @since 6.3
*/
public static final String FAILED_TO_GENERATE_LOGOUT_RESPONSE = "failed_to_generate_logout_response";
private Saml2ErrorCodes() { private Saml2ErrorCodes() {
} }

View File

@ -240,9 +240,8 @@ final class BaseOpenSamlLogoutResponseResolver implements Saml2LogoutResponseRes
private String getSamlStatus(Saml2AuthenticationException exception) { private String getSamlStatus(Saml2AuthenticationException exception) {
Saml2Error saml2Error = exception.getSaml2Error(); Saml2Error saml2Error = exception.getSaml2Error();
return switch (saml2Error.getErrorCode()) { return switch (saml2Error.getErrorCode()) {
case Saml2ErrorCodes.MISSING_LOGOUT_REQUEST_ENDPOINT, Saml2ErrorCodes.INVALID_BINDING -> case Saml2ErrorCodes.INVALID_DESTINATION -> StatusCode.REQUEST_DENIED;
StatusCode.REQUEST_DENIED; case Saml2ErrorCodes.INVALID_REQUEST -> StatusCode.REQUESTER;
case Saml2ErrorCodes.INVALID_LOGOUT_REQUEST -> StatusCode.REQUESTER;
default -> StatusCode.RESPONDER; default -> StatusCode.RESPONDER;
}; };
} }

View File

@ -113,27 +113,44 @@ public final class Saml2LogoutRequestFilter extends OncePerRequestFilter {
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException { throws ServletException, IOException {
Authentication authentication = this.securityContextHolderStrategy.getContext().getAuthentication(); Authentication authentication = this.securityContextHolderStrategy.getContext().getAuthentication();
Saml2LogoutRequestValidatorParameters parameters;
try { try {
Saml2LogoutRequestValidatorParameters parameters = this.logoutRequestResolver.resolve(request, parameters = this.logoutRequestResolver.resolve(request, authentication);
authentication); }
if (parameters == null) { catch (Saml2AuthenticationException ex) {
chain.doFilter(request, response); this.logger.trace("Did not process logout request since failed to find requested RelyingPartyRegistration");
return; response.sendError(HttpServletResponse.SC_BAD_REQUEST);
} return;
}
if (parameters == null) {
chain.doFilter(request, response);
return;
}
Saml2LogoutResponse logoutResponse = processLogoutRequest(request, response, authentication, parameters); try {
sendLogoutResponse(request, response, logoutResponse); validateLogoutRequest(request, parameters);
} }
catch (Saml2AuthenticationException ex) { catch (Saml2AuthenticationException ex) {
Saml2LogoutResponse errorLogoutResponse = this.logoutResponseResolver.resolve(request, authentication, ex); Saml2LogoutResponse errorLogoutResponse = this.logoutResponseResolver.resolve(request, authentication, ex);
if (errorLogoutResponse == null) { if (errorLogoutResponse == null) {
this.logger.trace("Returning error since no error logout response could be generated", ex); this.logger.trace(LogMessage.format(
"Returning error since no error logout response could be generated: %s", ex.getSaml2Error()));
response.sendError(HttpServletResponse.SC_UNAUTHORIZED); response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return; return;
} }
sendLogoutResponse(request, response, errorLogoutResponse); sendLogoutResponse(request, response, errorLogoutResponse);
return;
} }
this.handler.logout(request, response, authentication);
Saml2LogoutResponse logoutResponse = this.logoutResponseResolver.resolve(request, authentication);
if (logoutResponse == null) {
this.logger.trace("Returning error since no logout response generated");
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return;
}
sendLogoutResponse(request, response, logoutResponse);
} }
public void setLogoutRequestMatcher(RequestMatcher logoutRequestMatcher) { public void setLogoutRequestMatcher(RequestMatcher logoutRequestMatcher) {
@ -155,13 +172,12 @@ public final class Saml2LogoutRequestFilter extends OncePerRequestFilter {
this.securityContextHolderStrategy = securityContextHolderStrategy; this.securityContextHolderStrategy = securityContextHolderStrategy;
} }
private Saml2LogoutResponse processLogoutRequest(HttpServletRequest request, HttpServletResponse response, private void validateLogoutRequest(HttpServletRequest request, Saml2LogoutRequestValidatorParameters parameters) {
Authentication authentication, Saml2LogoutRequestValidatorParameters parameters) {
RelyingPartyRegistration registration = parameters.getRelyingPartyRegistration(); RelyingPartyRegistration registration = parameters.getRelyingPartyRegistration();
if (registration.getSingleLogoutServiceLocation() == null) { if (registration.getSingleLogoutServiceLocation() == null) {
this.logger.trace( this.logger.trace(
"Did not process logout request since RelyingPartyRegistration has not been configured with a logout request endpoint"); "Did not process logout request since RelyingPartyRegistration has not been configured with a logout request endpoint");
throw new Saml2AuthenticationException(new Saml2Error(Saml2ErrorCodes.MISSING_LOGOUT_REQUEST_ENDPOINT, throw new Saml2AuthenticationException(new Saml2Error(Saml2ErrorCodes.INVALID_DESTINATION,
"RelyingPartyRegistration has not been configured with a logout request endpoint")); "RelyingPartyRegistration has not been configured with a logout request endpoint"));
} }
@ -169,24 +185,15 @@ public final class Saml2LogoutRequestFilter extends OncePerRequestFilter {
if (!registration.getSingleLogoutServiceBindings().contains(saml2MessageBinding)) { if (!registration.getSingleLogoutServiceBindings().contains(saml2MessageBinding)) {
this.logger.trace("Did not process logout request since used incorrect binding"); this.logger.trace("Did not process logout request since used incorrect binding");
throw new Saml2AuthenticationException( throw new Saml2AuthenticationException(
new Saml2Error(Saml2ErrorCodes.INVALID_BINDING, "Logout request used invalid binding")); new Saml2Error(Saml2ErrorCodes.INVALID_REQUEST, "Logout request used invalid binding"));
} }
Saml2LogoutValidatorResult result = this.logoutRequestValidator.validate(parameters); Saml2LogoutValidatorResult result = this.logoutRequestValidator.validate(parameters);
if (result.hasErrors()) { if (result.hasErrors()) {
this.logger.debug(LogMessage.format("Failed to validate LogoutRequest: %s", result.getErrors())); this.logger.debug(LogMessage.format("Failed to validate LogoutRequest: %s", result.getErrors()));
throw new Saml2AuthenticationException( throw new Saml2AuthenticationException(
new Saml2Error(Saml2ErrorCodes.INVALID_LOGOUT_REQUEST, "Failed to validate the logout request")); new Saml2Error(Saml2ErrorCodes.INVALID_REQUEST, "Failed to validate the logout request"));
} }
this.handler.logout(request, response, authentication);
Saml2LogoutResponse logoutResponse = this.logoutResponseResolver.resolve(request, authentication);
if (logoutResponse == null) {
this.logger.trace("Returning error since no logout response generated");
throw new Saml2AuthenticationException(new Saml2Error(Saml2ErrorCodes.FAILED_TO_GENERATE_LOGOUT_RESPONSE,
"Could not generated logout response"));
}
return logoutResponse;
} }
private void sendLogoutResponse(HttpServletRequest request, HttpServletResponse response, private void sendLogoutResponse(HttpServletRequest request, HttpServletResponse response,

View File

@ -53,7 +53,9 @@ public interface Saml2LogoutResponseResolver {
* processed * processed
* @return a signed and serialized SAML 2.0 Logout Response * @return a signed and serialized SAML 2.0 Logout Response
*/ */
Saml2LogoutResponse resolve(HttpServletRequest request, Authentication authentication, default Saml2LogoutResponse resolve(HttpServletRequest request, Authentication authentication,
Saml2AuthenticationException authenticationException); Saml2AuthenticationException authenticationException) {
return null;
}
} }

View File

@ -65,7 +65,7 @@ public class OpenSaml4LogoutResponseResolverTests {
logoutResponseResolver.setParametersConsumer(parametersConsumer); logoutResponseResolver.setParametersConsumer(parametersConsumer);
MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletRequest request = new MockHttpServletRequest();
RelyingPartyRegistration registration = TestRelyingPartyRegistrations.relyingPartyRegistration() RelyingPartyRegistration registration = TestRelyingPartyRegistrations.relyingPartyRegistration()
.assertingPartyDetails( .assertingPartyMetadata(
(party) -> party.singleLogoutServiceResponseLocation("https://ap.example.com/logout")) (party) -> party.singleLogoutServiceResponseLocation("https://ap.example.com/logout"))
.build(); .build();
Authentication authentication = new TestingAuthenticationToken("user", "password"); Authentication authentication = new TestingAuthenticationToken("user", "password");
@ -109,19 +109,10 @@ public class OpenSaml4LogoutResponseResolverTests {
private static Stream<Arguments> provideAuthExceptionAndExpectedSamlStatusCode() { private static Stream<Arguments> provideAuthExceptionAndExpectedSamlStatusCode() {
return Stream.of( return Stream.of(
Arguments.of( Arguments.of(new Saml2AuthenticationException(new Saml2Error(Saml2ErrorCodes.INVALID_DESTINATION, "")),
new Saml2AuthenticationException(
new Saml2Error(Saml2ErrorCodes.MISSING_LOGOUT_REQUEST_ENDPOINT, "")),
StatusCode.REQUEST_DENIED), StatusCode.REQUEST_DENIED),
Arguments.of(new Saml2AuthenticationException(new Saml2Error(Saml2ErrorCodes.INVALID_BINDING, "")), Arguments.of(new Saml2AuthenticationException(new Saml2Error(Saml2ErrorCodes.INVALID_REQUEST, "")),
StatusCode.REQUEST_DENIED), StatusCode.REQUESTER)
Arguments.of(
new Saml2AuthenticationException(new Saml2Error(Saml2ErrorCodes.INVALID_LOGOUT_REQUEST, "")),
StatusCode.REQUESTER),
Arguments.of(
new Saml2AuthenticationException(
new Saml2Error(Saml2ErrorCodes.FAILED_TO_GENERATE_LOGOUT_RESPONSE, "")),
StatusCode.RESPONDER)
); );
} }

View File

@ -99,7 +99,7 @@ public class Saml2LogoutRequestFilterTests {
@Test @Test
public void doFilterWhenSamlRequestThenPosts() throws Exception { public void doFilterWhenSamlRequestThenPosts() throws Exception {
RelyingPartyRegistration registration = TestRelyingPartyRegistrations.full() RelyingPartyRegistration registration = TestRelyingPartyRegistrations.full()
.assertingPartyDetails((party) -> party.singleLogoutServiceBinding(Saml2MessageBinding.POST)) .assertingPartyMetadata((party) -> party.singleLogoutServiceBinding(Saml2MessageBinding.POST))
.build(); .build();
Authentication authentication = new TestingAuthenticationToken("user", "password"); Authentication authentication = new TestingAuthenticationToken("user", "password");
given(this.securityContextHolderStrategy.getContext()).willReturn(new SecurityContextImpl(authentication)); given(this.securityContextHolderStrategy.getContext()).willReturn(new SecurityContextImpl(authentication));
@ -149,7 +149,7 @@ public class Saml2LogoutRequestFilterTests {
@Test @Test
public void doFilterWhenValidationFailsErrorLogoutResponseIsPosted() throws Exception { public void doFilterWhenValidationFailsErrorLogoutResponseIsPosted() throws Exception {
RelyingPartyRegistration registration = TestRelyingPartyRegistrations.full() RelyingPartyRegistration registration = TestRelyingPartyRegistrations.full()
.assertingPartyDetails((party) -> party.singleLogoutServiceBinding(Saml2MessageBinding.POST)) .assertingPartyMetadata((party) -> party.singleLogoutServiceBinding(Saml2MessageBinding.POST))
.build(); .build();
Authentication authentication = new TestingAuthenticationToken("user", "password"); Authentication authentication = new TestingAuthenticationToken("user", "password");
SecurityContextHolder.getContext().setAuthentication(authentication); SecurityContextHolder.getContext().setAuthentication(authentication);
@ -165,7 +165,7 @@ public class Saml2LogoutRequestFilterTests {
given(this.logoutRequestValidator.validate(any())) given(this.logoutRequestValidator.validate(any()))
.willReturn(Saml2LogoutValidatorResult.withErrors(new Saml2Error("error", "description")).build()); .willReturn(Saml2LogoutValidatorResult.withErrors(new Saml2Error("error", "description")).build());
given(this.logoutResponseResolver.resolve(any(), any(), given(this.logoutResponseResolver.resolve(any(), any(),
argThat((ex) -> ex.getSaml2Error().getErrorCode().equals(Saml2ErrorCodes.INVALID_LOGOUT_REQUEST)))) argThat((ex) -> ex.getSaml2Error().getErrorCode().equals(Saml2ErrorCodes.INVALID_REQUEST))))
.willReturn(logoutResponse); .willReturn(logoutResponse);
this.logoutRequestProcessingFilter.doFilter(request, response, new MockFilterChain()); this.logoutRequestProcessingFilter.doFilter(request, response, new MockFilterChain());
@ -173,7 +173,7 @@ public class Saml2LogoutRequestFilterTests {
checkResponse(response.getContentAsString(), registration); checkResponse(response.getContentAsString(), registration);
verify(this.logoutRequestValidator).validate(any()); verify(this.logoutRequestValidator).validate(any());
verify(this.logoutResponseResolver).resolve(any(), any(), verify(this.logoutResponseResolver).resolve(any(), any(),
argThat((ex) -> ex.getSaml2Error().getErrorCode().equals(Saml2ErrorCodes.INVALID_LOGOUT_REQUEST))); argThat((ex) -> ex.getSaml2Error().getErrorCode().equals(Saml2ErrorCodes.INVALID_REQUEST)));
verifyNoInteractions(this.logoutHandler); verifyNoInteractions(this.logoutHandler);
} }
@ -186,7 +186,7 @@ public class Saml2LogoutRequestFilterTests {
request.setParameter(Saml2ParameterNames.SAML_REQUEST, "request"); request.setParameter(Saml2ParameterNames.SAML_REQUEST, "request");
MockHttpServletResponse response = new MockHttpServletResponse(); MockHttpServletResponse response = new MockHttpServletResponse();
RelyingPartyRegistration registration = TestRelyingPartyRegistrations.full() RelyingPartyRegistration registration = TestRelyingPartyRegistrations.full()
.assertingPartyDetails((party) -> party.singleLogoutServiceBinding(Saml2MessageBinding.POST)) .assertingPartyMetadata((party) -> party.singleLogoutServiceBinding(Saml2MessageBinding.POST))
.singleLogoutServiceLocation(null) .singleLogoutServiceLocation(null)
.build(); .build();
Saml2LogoutResponse logoutResponse = Saml2LogoutResponse.withRelyingPartyRegistration(registration) Saml2LogoutResponse logoutResponse = Saml2LogoutResponse.withRelyingPartyRegistration(registration)
@ -194,15 +194,15 @@ public class Saml2LogoutRequestFilterTests {
.build(); .build();
given(this.relyingPartyRegistrationResolver.resolve(any(), any())).willReturn(registration); given(this.relyingPartyRegistrationResolver.resolve(any(), any())).willReturn(registration);
given(this.logoutResponseResolver.resolve(any(), any(), argThat( given(this.logoutResponseResolver.resolve(any(), any(),
(ex) -> ex.getSaml2Error().getErrorCode().equals(Saml2ErrorCodes.MISSING_LOGOUT_REQUEST_ENDPOINT)))) argThat((ex) -> ex.getSaml2Error().getErrorCode().equals(Saml2ErrorCodes.INVALID_DESTINATION))))
.willReturn(logoutResponse); .willReturn(logoutResponse);
this.logoutRequestProcessingFilter.doFilterInternal(request, response, new MockFilterChain()); this.logoutRequestProcessingFilter.doFilterInternal(request, response, new MockFilterChain());
checkResponse(response.getContentAsString(), registration); checkResponse(response.getContentAsString(), registration);
verify(this.logoutResponseResolver).resolve(any(), any(), argThat( verify(this.logoutResponseResolver).resolve(any(), any(),
(ex) -> ex.getSaml2Error().getErrorCode().equals(Saml2ErrorCodes.MISSING_LOGOUT_REQUEST_ENDPOINT))); argThat((ex) -> ex.getSaml2Error().getErrorCode().equals(Saml2ErrorCodes.INVALID_DESTINATION)));
verifyNoInteractions(this.logoutHandler); verifyNoInteractions(this.logoutHandler);
} }
@ -215,7 +215,7 @@ public class Saml2LogoutRequestFilterTests {
request.setParameter(Saml2ParameterNames.SAML_REQUEST, "request"); request.setParameter(Saml2ParameterNames.SAML_REQUEST, "request");
MockHttpServletResponse response = new MockHttpServletResponse(); MockHttpServletResponse response = new MockHttpServletResponse();
RelyingPartyRegistration registration = TestRelyingPartyRegistrations.full() RelyingPartyRegistration registration = TestRelyingPartyRegistrations.full()
.assertingPartyDetails((party) -> party.singleLogoutServiceBinding(Saml2MessageBinding.POST)) .assertingPartyMetadata((party) -> party.singleLogoutServiceBinding(Saml2MessageBinding.POST))
.singleLogoutServiceBindings((bindings) -> { .singleLogoutServiceBindings((bindings) -> {
bindings.clear(); bindings.clear();
bindings.add(Saml2MessageBinding.REDIRECT); bindings.add(Saml2MessageBinding.REDIRECT);
@ -227,14 +227,14 @@ public class Saml2LogoutRequestFilterTests {
given(this.relyingPartyRegistrationResolver.resolve(any(), any())).willReturn(registration); given(this.relyingPartyRegistrationResolver.resolve(any(), any())).willReturn(registration);
given(this.logoutResponseResolver.resolve(any(), any(), given(this.logoutResponseResolver.resolve(any(), any(),
argThat((ex) -> ex.getSaml2Error().getErrorCode().equals(Saml2ErrorCodes.INVALID_BINDING)))) argThat((ex) -> ex.getSaml2Error().getErrorCode().equals(Saml2ErrorCodes.INVALID_REQUEST))))
.willReturn(logoutResponse); .willReturn(logoutResponse);
this.logoutRequestProcessingFilter.doFilterInternal(request, response, new MockFilterChain()); this.logoutRequestProcessingFilter.doFilterInternal(request, response, new MockFilterChain());
checkResponse(response.getContentAsString(), registration); checkResponse(response.getContentAsString(), registration);
verify(this.logoutResponseResolver).resolve(any(), any(), verify(this.logoutResponseResolver).resolve(any(), any(),
argThat((ex) -> ex.getSaml2Error().getErrorCode().equals(Saml2ErrorCodes.INVALID_BINDING))); argThat((ex) -> ex.getSaml2Error().getErrorCode().equals(Saml2ErrorCodes.INVALID_REQUEST)));
verifyNoInteractions(this.logoutHandler); verifyNoInteractions(this.logoutHandler);
} }
@ -247,7 +247,7 @@ public class Saml2LogoutRequestFilterTests {
request.setParameter(Saml2ParameterNames.SAML_REQUEST, "request"); request.setParameter(Saml2ParameterNames.SAML_REQUEST, "request");
MockHttpServletResponse response = new MockHttpServletResponse(); MockHttpServletResponse response = new MockHttpServletResponse();
RelyingPartyRegistration registration = TestRelyingPartyRegistrations.full() RelyingPartyRegistration registration = TestRelyingPartyRegistrations.full()
.assertingPartyDetails((party) -> party.singleLogoutServiceBinding(Saml2MessageBinding.POST)) .assertingPartyMetadata((party) -> party.singleLogoutServiceBinding(Saml2MessageBinding.POST))
.singleLogoutServiceBindings((bindings) -> { .singleLogoutServiceBindings((bindings) -> {
bindings.clear(); bindings.clear();
bindings.add(Saml2MessageBinding.REDIRECT); bindings.add(Saml2MessageBinding.REDIRECT);
@ -256,14 +256,14 @@ public class Saml2LogoutRequestFilterTests {
given(this.relyingPartyRegistrationResolver.resolve(any(), any())).willReturn(registration); given(this.relyingPartyRegistrationResolver.resolve(any(), any())).willReturn(registration);
given(this.logoutResponseResolver.resolve(any(), any(), given(this.logoutResponseResolver.resolve(any(), any(),
argThat((ex) -> ex.getSaml2Error().getErrorCode().equals(Saml2ErrorCodes.INVALID_BINDING)))) argThat((ex) -> ex.getSaml2Error().getErrorCode().equals(Saml2ErrorCodes.INVALID_REQUEST))))
.willReturn(null); .willReturn(null);
this.logoutRequestProcessingFilter.doFilterInternal(request, response, new MockFilterChain()); this.logoutRequestProcessingFilter.doFilterInternal(request, response, new MockFilterChain());
assertThat(response.getStatus()).isEqualTo(401); assertThat(response.getStatus()).isEqualTo(401);
verify(this.logoutResponseResolver).resolve(any(), any(), verify(this.logoutResponseResolver).resolve(any(), any(),
argThat((ex) -> ex.getSaml2Error().getErrorCode().equals(Saml2ErrorCodes.INVALID_BINDING))); argThat((ex) -> ex.getSaml2Error().getErrorCode().equals(Saml2ErrorCodes.INVALID_REQUEST)));
verifyNoInteractions(this.logoutHandler); verifyNoInteractions(this.logoutHandler);
} }