Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ subprojects {
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
if (details.requested.group == 'org.opensaml' && details.requested.name.startsWith("opensaml-")) {
details.useVersion "${versions.opensaml}"
details.because 'Spring Security 5.8.x allows OpenSAML 3 or 4. OpenSAML 3 has reached its end-of-life. Spring Security 6 drops support for 3, using 4.'
details.because 'Pinning all opensaml modules to the same version for OpenSAML 5 migration.'
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ versions.springBootVersion = "3.5.14"
versions.guavaVersion = "33.6.0-jre"
versions.seleniumVersion = "4.43.0"
versions.braveVersion = "6.3.1"
versions.opensaml = "4.3.2"
// OpenSAML 5.2.x pulls non-FIPS classes; stay on 5.1.x until resolved
versions.opensaml = "5.1.6"

// Versions we're overriding from the Spring Boot Bom (Dependabot does not issue PRs to bump these versions, so we need to manually bump them)
ext["selenium.version"] = "${versions.seleniumVersion}" // Selenium for integration tests only
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
package org.cloudfoundry.identity.uaa.authentication;

import org.springframework.security.saml2.core.Saml2Error;
import org.springframework.security.saml2.provider.service.authentication.logout.OpenSamlLogoutRequestValidator;
import org.springframework.security.saml2.provider.service.authentication.logout.OpenSaml5LogoutRequestValidator;
import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutRequestValidator;
Comment thread
strehle marked this conversation as resolved.
import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutRequestValidatorParameters;
import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutValidatorResult;

import java.util.Collection;

/**
* Delegates SAML logout request validation to {@link OpenSamlLogoutRequestValidator},
* Delegates SAML logout request validation to {@link OpenSaml5LogoutRequestValidator},
* but ignores errors due to missing signatures.
*/
Comment thread
strehle marked this conversation as resolved.
public class SamlLogoutRequestValidator implements Saml2LogoutRequestValidator {

private final Saml2LogoutRequestValidator delegate;

public SamlLogoutRequestValidator() {
this.delegate = new OpenSamlLogoutRequestValidator();
this.delegate = new OpenSaml5LogoutRequestValidator();
}
Comment thread
strehle marked this conversation as resolved.

public SamlLogoutRequestValidator(Saml2LogoutRequestValidator delegate) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package org.cloudfoundry.identity.uaa.authentication;

import org.springframework.security.saml2.core.Saml2Error;
import org.springframework.security.saml2.provider.service.authentication.logout.OpenSamlLogoutResponseValidator;
import org.springframework.security.saml2.provider.service.authentication.logout.OpenSaml5LogoutResponseValidator;
import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutResponseValidator;
Comment thread
strehle marked this conversation as resolved.
import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutResponseValidatorParameters;
import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutValidatorResult;

import java.util.Collection;

/**
* Delegates SAML logout responses validation to {@link OpenSamlLogoutResponseValidator}
* Delegates SAML logout responses validation to {@link OpenSaml5LogoutResponseValidator}
* but ignores errors due to missing signatures.
*/
Comment thread
strehle marked this conversation as resolved.

Expand All @@ -18,7 +18,7 @@ public class SamlLogoutResponseValidator implements Saml2LogoutResponseValidator
private final Saml2LogoutResponseValidator delegate;

public SamlLogoutResponseValidator() {
this.delegate = new OpenSamlLogoutResponseValidator();
this.delegate = new OpenSaml5LogoutResponseValidator();
}
Comment thread
strehle marked this conversation as resolved.

public SamlLogoutResponseValidator(Saml2LogoutResponseValidator delegate) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

import jakarta.annotation.Nonnull;
import lombok.Getter;
import net.shibboleth.utilities.java.support.xml.ParserPool;
import net.shibboleth.shared.xml.ParserPool;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.cloudfoundry.identity.uaa.util.UaaUrlUtils;
Expand Down Expand Up @@ -106,13 +106,17 @@
import static org.cloudfoundry.identity.uaa.util.UaaUrlUtils.normalizeUrlForPortComparison;

/**
* This was copied from Spring Security, and modified to work with Open SAML 4.0.x
* The original class only works with Open SAML 4.1.x+
* This was originally copied from Spring Security, and modified to work with Open SAML 4.0.x,
* then further updated for Open SAML 5.x compatibility.
* <p/>
* Once we can move to the spring-security version of OpenSaml4AuthenticationProvider,
* this class should be removed, along with OpenSamlDecryptionUtils and OpenSamlVerificationUtils.
* Key changes from OpenSAML 4 to 5:
* - {@code net.shibboleth.utilities.java.support} packages moved to {@code net.shibboleth.shared}
* - {@code SAML20AssertionValidator} constructor gains a 4th {@code AssertionValidator} parameter
* - {@code ValidationContext.getValidationFailureMessage()} renamed to {@code getValidationFailureMessages()}
* - {@code ConditionValidator.validate()} now throws {@code AssertionValidationException}
* - {@code BearerSubjectConfirmationValidator.validateAddress()} removed (address validation dropped)
*/
public final class OpenSaml4AuthenticationProvider implements AuthenticationProvider, ZoneAware {
public final class OpenSaml5AuthenticationProvider implements AuthenticationProvider, ZoneAware {

static {
SamlConfiguration.setupOpenSaml();
Expand Down Expand Up @@ -147,9 +151,9 @@ public final class OpenSaml4AuthenticationProvider implements AuthenticationProv
private Converter<ResponseToken, ? extends AbstractAuthenticationToken> responseAuthenticationConverter = createDefaultResponseAuthenticationConverter();

/**
* Creates an {@link OpenSaml4AuthenticationProvider}
* Creates an {@link OpenSaml5AuthenticationProvider}
*/
public OpenSaml4AuthenticationProvider() {
public OpenSaml5AuthenticationProvider() {
XMLObjectProviderRegistry registry = ConfigurationService.get(XMLObjectProviderRegistry.class);
this.responseUnmarshaller = (ResponseUnmarshaller) registry.getUnmarshallerFactory()
.getUnmarshaller(Response.DEFAULT_ELEMENT_NAME);
Expand All @@ -163,7 +167,7 @@ public OpenSaml4AuthenticationProvider() {
* {@link #createDefaultResponseValidator()}, like so:
*
* <pre>
* OpenSaml4AuthenticationProvider provider = new OpenSaml4AuthenticationProvider();
* OpenSaml5AuthenticationProvider provider = new OpenSaml5AuthenticationProvider();
* provider.setResponseValidator(responseToken -&gt; {
* Saml2ResponseValidatorResult result = createDefaultResponseValidator()
* .convert(responseToken)
Expand Down Expand Up @@ -579,7 +583,7 @@ private static Converter<AssertionToken, Saml2ResponseValidatorResult> createAss
}
String message = "Invalid assertion [%s] for SAML response [%s]: %s".formatted(assertion.getID(),
assertion.getParent() != null ? ((Response) assertion.getParent()).getID() : assertion.getID(),
context.getValidationFailureMessage());
String.join("; ", context.getValidationFailureMessages()));
return Saml2ResponseValidatorResult.failure(new Saml2Error(errorCode, message));
};
}
Expand Down Expand Up @@ -619,6 +623,8 @@ private static ValidationContext createValidationContext(AssertionToken assertio
params.put(SAML2AssertionValidationParameters.COND_VALID_AUDIENCES, Collections.singleton(audience));
params.put(SAML2AssertionValidationParameters.SC_VALID_RECIPIENTS, recipientList);
params.put(SAML2AssertionValidationParameters.VALID_ISSUERS, Collections.singleton(assertingPartyEntityId));
// Disable address checking - we don't track valid client addresses
params.put(SAML2AssertionValidationParameters.SC_CHECK_ADDRESS, false);
paramsConsumer.accept(params);
return new ValidationContext(params);
}
Expand Down Expand Up @@ -699,18 +705,11 @@ public ValidationResult validate(Condition condition, Assertion assertion, Valid
}
});
conditions.add(new ProxyRestrictionConditionValidator());
subjects.add(new BearerSubjectConfirmationValidator() {
@Override
protected ValidationResult validateAddress(SubjectConfirmation confirmation, Assertion assertion,
ValidationContext context, boolean required) {
// applications should validate their own addresses - gh-7514
return ValidationResult.VALID;
}
});
subjects.add(new BearerSubjectConfirmationValidator());
}

private static final SAML20AssertionValidator attributeValidator = new SAML20AssertionValidator(conditions,
subjects, statements, null, null) {
subjects, statements, null, null, null) {
@Nonnull
@Override
protected ValidationResult validateSignature(Assertion token, ValidationContext context) {
Expand All @@ -719,7 +718,7 @@ protected ValidationResult validateSignature(Assertion token, ValidationContext
};

static SAML20AssertionValidator createSignatureValidator(SignatureTrustEngine engine) {
return new SAML20AssertionValidator(new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), engine,
return new SAML20AssertionValidator(new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), null, engine,
validator) {
@Nonnull
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@
import java.util.Collection;

/**
* This class was copied from Spring Security 5.6.0 to get the OpenSaml4AuthenticationProvider to work.
* It should be removed once we are able to more to the spring-security version of OpenSaml4AuthenticationProvider.
* This class was copied from Spring Security 5.6.0 to get the OpenSaml5AuthenticationProvider to work.
* It should be removed once we are able to move to the spring-security version of OpenSaml5AuthenticationProvider.
* <p/>
* Utility methods for decrypting SAML components with OpenSAML
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

package org.cloudfoundry.identity.uaa.provider.saml;

import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
import net.shibboleth.shared.resolver.CriteriaSet;
import org.opensaml.core.criterion.EntityIdCriterion;
import org.opensaml.saml.common.xml.SAMLConstants;
import org.opensaml.saml.criterion.ProtocolCriterion;
Expand Down Expand Up @@ -48,8 +48,8 @@
import java.util.Set;

/**
* This class was copied from Spring Security 5.6.0 to get the OpenSaml4AuthenticationProvider to work.
* It should be removed once we are able to more to the spring-security version of OpenSaml4AuthenticationProvider.
* This class was copied from Spring Security 5.6.0 to get the OpenSaml5AuthenticationProvider to work.
* It should be removed once we are able to move to the spring-security version of OpenSaml5AuthenticationProvider.
* <p/>
* Utility methods for verifying SAML component signatures with OpenSAML
* <p>
Expand Down
Loading
Loading