-
Notifications
You must be signed in to change notification settings - Fork 6.1k
Send saml logout response even when validation errors happen #14676
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,6 +31,7 @@ | |
import org.springframework.security.core.context.SecurityContextHolder; | ||
import org.springframework.security.core.context.SecurityContextHolderStrategy; | ||
import org.springframework.security.saml2.core.Saml2Error; | ||
import org.springframework.security.saml2.core.Saml2ErrorCodes; | ||
import org.springframework.security.saml2.core.Saml2ParameterNames; | ||
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal; | ||
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationException; | ||
|
@@ -125,40 +126,31 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse | |
chain.doFilter(request, response); | ||
return; | ||
} | ||
RelyingPartyRegistration registration = parameters.getRelyingPartyRegistration(); | ||
if (registration.getSingleLogoutServiceLocation() == null) { | ||
this.logger.trace( | ||
"Did not process logout request since RelyingPartyRegistration has not been configured with a logout request endpoint"); | ||
response.sendError(HttpServletResponse.SC_UNAUTHORIZED); | ||
return; | ||
} | ||
|
||
Saml2MessageBinding saml2MessageBinding = Saml2MessageBindingUtils.resolveBinding(request); | ||
if (!registration.getSingleLogoutServiceBindings().contains(saml2MessageBinding)) { | ||
this.logger.trace("Did not process logout request since used incorrect binding"); | ||
response.sendError(HttpServletResponse.SC_UNAUTHORIZED); | ||
return; | ||
try { | ||
validateLogoutRequest(request, parameters); | ||
} | ||
catch (Saml2AuthenticationException ex) { | ||
Saml2LogoutResponse errorLogoutResponse = this.logoutResponseResolver.resolve(request, authentication, ex); | ||
if (errorLogoutResponse == null) { | ||
this.logger.trace(LogMessage.format( | ||
"Returning error since no error logout response could be generated: %s", ex.getSaml2Error())); | ||
response.sendError(HttpServletResponse.SC_UNAUTHORIZED); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please have this include the error message from the exception so that it gives the same information that this did There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
return; | ||
} | ||
|
||
Saml2LogoutValidatorResult result = this.logoutRequestValidator.validate(parameters); | ||
if (result.hasErrors()) { | ||
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, result.getErrors().iterator().next().toString()); | ||
this.logger.debug(LogMessage.format("Failed to validate LogoutRequest: %s", result.getErrors())); | ||
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 401 since no logout response generated"); | ||
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); | ||
this.logger.trace("Returning error since no logout response generated"); | ||
response.sendError(HttpServletResponse.SC_UNAUTHORIZED); | ||
return; | ||
} | ||
if (logoutResponse.getBinding() == Saml2MessageBinding.REDIRECT) { | ||
doRedirect(request, response, logoutResponse); | ||
} | ||
else { | ||
doPost(response, logoutResponse); | ||
} | ||
sendLogoutResponse(request, response, logoutResponse); | ||
} | ||
|
||
public void setLogoutRequestMatcher(RequestMatcher logoutRequestMatcher) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See if you can avoid moving these, so that it's easier to identify the changes to fix the bug. |
||
|
@@ -180,6 +172,40 @@ public void setSecurityContextHolderStrategy(SecurityContextHolderStrategy secur | |
this.securityContextHolderStrategy = securityContextHolderStrategy; | ||
} | ||
|
||
private void validateLogoutRequest(HttpServletRequest request, Saml2LogoutRequestValidatorParameters parameters) { | ||
RelyingPartyRegistration registration = parameters.getRelyingPartyRegistration(); | ||
if (registration.getSingleLogoutServiceLocation() == null) { | ||
this.logger.trace( | ||
"Did not process logout request since RelyingPartyRegistration has not been configured with a logout request endpoint"); | ||
throw new Saml2AuthenticationException(new Saml2Error(Saml2ErrorCodes.INVALID_DESTINATION, | ||
"RelyingPartyRegistration has not been configured with a logout request endpoint")); | ||
} | ||
|
||
Saml2MessageBinding saml2MessageBinding = Saml2MessageBindingUtils.resolveBinding(request); | ||
if (!registration.getSingleLogoutServiceBindings().contains(saml2MessageBinding)) { | ||
this.logger.trace("Did not process logout request since used incorrect binding"); | ||
throw new Saml2AuthenticationException( | ||
new Saml2Error(Saml2ErrorCodes.INVALID_REQUEST, "Logout request used invalid binding")); | ||
} | ||
|
||
Saml2LogoutValidatorResult result = this.logoutRequestValidator.validate(parameters); | ||
if (result.hasErrors()) { | ||
this.logger.debug(LogMessage.format("Failed to validate LogoutRequest: %s", result.getErrors())); | ||
throw new Saml2AuthenticationException( | ||
new Saml2Error(Saml2ErrorCodes.INVALID_REQUEST, "Failed to validate the logout request")); | ||
} | ||
} | ||
|
||
private void sendLogoutResponse(HttpServletRequest request, HttpServletResponse response, | ||
Saml2LogoutResponse logoutResponse) throws IOException { | ||
if (logoutResponse.getBinding() == Saml2MessageBinding.REDIRECT) { | ||
doRedirect(request, response, logoutResponse); | ||
} | ||
else { | ||
doPost(response, logoutResponse); | ||
} | ||
} | ||
|
||
private void doRedirect(HttpServletRequest request, HttpServletResponse response, | ||
Saml2LogoutResponse logoutResponse) throws IOException { | ||
String location = logoutResponse.getResponseLocation(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, this makes sense to change this test since it is what the bug is about