Skip to content

Commit

Permalink
OP-22767: Bugfix for SAML2 Authentication Validation InResponseTo and…
Browse files Browse the repository at this point in the history
… Assertion disable flags (#490)
  • Loading branch information
sudhakaropsmx authored Oct 24, 2024
1 parent 33c8e13 commit 13f69db
Showing 1 changed file with 70 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@

package com.opsmx.spinnaker.gate.security.saml;

import static org.springframework.security.saml2.core.Saml2ErrorCodes.INVALID_ASSERTION;
import static org.springframework.security.saml2.core.Saml2ErrorCodes.INVALID_IN_RESPONSE_TO;

import com.netflix.spectator.api.Registry;
import com.netflix.spinnaker.fiat.shared.FiatClientConfigurationProperties;
import com.netflix.spinnaker.gate.config.AuthConfig;
Expand All @@ -28,7 +31,9 @@
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.opensaml.saml.saml2.core.Assertion;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -46,6 +51,8 @@
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.saml2.core.Saml2Error;
import org.springframework.security.saml2.core.Saml2ResponseValidatorResult;
import org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationProvider;
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal;
import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
Expand Down Expand Up @@ -90,6 +97,12 @@ public class SamlSecurityConfiguration {
public static final String defaultFilterUrl =
"{baseUrl}" + Saml2WebSsoAuthenticationFilter.DEFAULT_FILTER_PROCESSES_URI;

@Value("${spring.security.saml2.validation.inresponseto:false}")
private boolean ignoreInResponseToValidation;

@Value("${spring.security.saml2.validation.assertion:false}")
private boolean ignoreAssertionValidation;

@Bean
public UserDetailsService userDetailsService() {
return username -> {
Expand All @@ -112,6 +125,14 @@ public RememberMeServices rememberMeServices(UserDetailsService userDetailsServi
public OpenSaml4AuthenticationProvider authenticationProvider() {
var authProvider = new OpenSaml4AuthenticationProvider();
authProvider.setResponseAuthenticationConverter(extractUserDetails());
log.debug("ignoreAssertionValidation :{}", ignoreAssertionValidation);
if (ignoreAssertionValidation) {
authProvider.setAssertionValidator(removeAssertionError());
}
log.debug("ignoreInResponseToValidation :{}", ignoreInResponseToValidation);
if (ignoreInResponseToValidation) {
authProvider.setResponseValidator(removeInResonseToError());
}
return authProvider;
}

Expand Down Expand Up @@ -208,7 +229,7 @@ public SecurityFilterChain samlFilterChain(

return responseToken -> {
List<String> roles = new ArrayList<>();
log.debug("responseToken : {}", responseToken);
log.debug("responseToken : {}", responseToken.getToken().getSaml2Response());
Saml2Authentication authentication = delegate.convert(responseToken);
Saml2AuthenticatedPrincipal principal =
(Saml2AuthenticatedPrincipal) authentication.getPrincipal();
Expand Down Expand Up @@ -276,6 +297,54 @@ public SecurityFilterChain samlFilterChain(
};
}

private Converter<OpenSaml4AuthenticationProvider.AssertionToken, Saml2ResponseValidatorResult>
removeAssertionError() {
log.debug("**remove assertion error from Saml2ResponseValidatorResult Errors**");
Converter<OpenSaml4AuthenticationProvider.AssertionToken, Saml2ResponseValidatorResult>
delegate = OpenSaml4AuthenticationProvider.createDefaultAssertionValidator();
return assertionToken -> {
log.debug("responseToken : {}", assertionToken.getToken().getSaml2Response());
Saml2ResponseValidatorResult result = delegate.convert(assertionToken);
result
.getErrors()
.forEach(
error ->
log.debug(
" error code :{} and description :{}",
error.getErrorCode(),
error.getDescription()));
Collection<Saml2Error> errors =
result.getErrors().stream()
.filter((error) -> !error.getErrorCode().equals(INVALID_ASSERTION))
.collect(Collectors.toList());
return Saml2ResponseValidatorResult.failure(errors);
};
}

private Converter<OpenSaml4AuthenticationProvider.ResponseToken, Saml2ResponseValidatorResult>
removeInResonseToError() {
log.debug("**remove InResonseTo error from Saml2ResponseValidatorResult Errors**");
Converter<OpenSaml4AuthenticationProvider.ResponseToken, Saml2ResponseValidatorResult>
delegate = OpenSaml4AuthenticationProvider.createDefaultResponseValidator();
return responseToken -> {
log.debug("responseToken : {}", responseToken.getToken().getSaml2Response());
Saml2ResponseValidatorResult result = delegate.convert(responseToken);
result
.getErrors()
.forEach(
error ->
log.debug(
" error code :{} and description :{}",
error.getErrorCode(),
error.getDescription()));
Collection<Saml2Error> errors =
result.getErrors().stream()
.filter((error) -> !error.getErrorCode().equals(INVALID_IN_RESPONSE_TO))
.collect(Collectors.toList());
return Saml2ResponseValidatorResult.failure(errors);
};
}

private void loginWithRoles(String username, List<String> roles) {

var id = registry.createId("fiat.login").withTag("type", "saml");
Expand Down

0 comments on commit 13f69db

Please sign in to comment.