diff --git a/build.gradle b/build.gradle index 14b06caf377..b840210324b 100644 --- a/build.gradle +++ b/build.gradle @@ -38,6 +38,11 @@ allprojects { mavenCentral() maven { url = uri("https://build.shibboleth.net/nexus/content/repositories/releases/") + content { + includeGroup("org.opensaml") + includeGroup("net.shibboleth") + includeGroupByRegex("net\\.shibboleth\\..*") + } } maven { url = uri("https://repository.mulesoft.org/releases/") } } @@ -79,7 +84,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.' } } } diff --git a/dependencies.gradle b/dependencies.gradle index eebbbe2f9d9..65713743adc 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -12,7 +12,7 @@ versions.springBootVersion = "3.5.13" versions.guavaVersion = "33.5.0-jre" versions.seleniumVersion = "4.43.0" versions.braveVersion = "6.3.1" -versions.opensaml = "4.3.2" +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 diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/OpenSaml4AuthenticationProvider.java b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/OpenSaml5AuthenticationProvider.java similarity index 94% rename from server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/OpenSaml4AuthenticationProvider.java rename to server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/OpenSaml5AuthenticationProvider.java index 4f33625a1f0..f4ad246c365 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/OpenSaml4AuthenticationProvider.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/OpenSaml5AuthenticationProvider.java @@ -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.zone.IdentityZone; @@ -34,6 +34,7 @@ import org.opensaml.core.xml.schema.XSInteger; import org.opensaml.core.xml.schema.XSString; import org.opensaml.core.xml.schema.XSURI; +import org.opensaml.saml.common.assertion.AssertionValidationException; import org.opensaml.saml.common.assertion.ValidationContext; import org.opensaml.saml.common.assertion.ValidationResult; import org.opensaml.saml.saml2.assertion.ConditionValidator; @@ -103,13 +104,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. *
- * 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(); @@ -144,9 +149,9 @@ public final class OpenSaml4AuthenticationProvider implements AuthenticationProv private Converter
- * OpenSaml4AuthenticationProvider provider = new OpenSaml4AuthenticationProvider();
+ * OpenSaml5AuthenticationProvider provider = new OpenSaml5AuthenticationProvider();
* provider.setResponseValidator(responseToken -> {
* Saml2ResponseValidatorResult result = createDefaultResponseValidator()
* .convert(responseToken)
@@ -574,7 +579,7 @@ private static Converter 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));
};
}
@@ -601,6 +606,8 @@ private static ValidationContext createValidationContext(AssertionToken assertio
params.put(SAML2AssertionValidationParameters.COND_VALID_AUDIENCES, Collections.singleton(audience));
params.put(SAML2AssertionValidationParameters.SC_VALID_RECIPIENTS, Collections.singleton(recipient));
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);
}
@@ -675,54 +682,53 @@ public QName getServicedCondition() {
@Nonnull
@Override
- public ValidationResult validate(Condition condition, Assertion assertion, ValidationContext context) {
+ public ValidationResult validate(Condition condition, Assertion assertion, ValidationContext context)
+ throws AssertionValidationException {
// applications should validate their own OneTimeUse conditions
return ValidationResult.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) {
+ protected ValidationResult validateSignature(Assertion token, ValidationContext context)
+ throws AssertionValidationException {
return ValidationResult.VALID;
}
};
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
- protected ValidationResult validateConditions(Assertion assertion, ValidationContext context) {
+ protected ValidationResult validateConditions(Assertion assertion, ValidationContext context)
+ throws AssertionValidationException {
return ValidationResult.VALID;
}
@Nonnull
@Override
- protected ValidationResult validateSubjectConfirmation(Assertion assertion, ValidationContext context) {
+ protected ValidationResult validateSubjectConfirmation(Assertion assertion, ValidationContext context)
+ throws AssertionValidationException {
return ValidationResult.VALID;
}
@Nonnull
@Override
- protected ValidationResult validateStatements(Assertion assertion, ValidationContext context) {
+ protected ValidationResult validateStatements(Assertion assertion, ValidationContext context)
+ throws AssertionValidationException {
return ValidationResult.VALID;
}
@Override
- protected ValidationResult validateIssuer(Assertion assertion, ValidationContext context) {
+ protected ValidationResult validateIssuer(Assertion assertion, ValidationContext context)
+ throws AssertionValidationException {
return ValidationResult.VALID;
}
};
diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/OpenSaml5MetadataResolver.java b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/OpenSaml5MetadataResolver.java
new file mode 100644
index 00000000000..fcf61adcf86
--- /dev/null
+++ b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/OpenSaml5MetadataResolver.java
@@ -0,0 +1,163 @@
+package org.cloudfoundry.identity.uaa.provider.saml;
+
+import net.shibboleth.shared.xml.SerializeSupport;
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.core.xml.io.Marshaller;
+import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.saml.common.xml.SAMLConstants;
+import org.opensaml.saml.saml2.metadata.AssertionConsumerService;
+import org.opensaml.saml.saml2.metadata.EntityDescriptor;
+import org.opensaml.saml.saml2.metadata.KeyDescriptor;
+import org.opensaml.saml.saml2.metadata.NameIDFormat;
+import org.opensaml.saml.saml2.metadata.SPSSODescriptor;
+import org.opensaml.saml.saml2.metadata.SingleLogoutService;
+import org.opensaml.security.credential.UsageType;
+import org.opensaml.xmlsec.signature.KeyInfo;
+import org.opensaml.xmlsec.signature.X509Certificate;
+import org.opensaml.xmlsec.signature.X509Data;
+import org.springframework.security.saml2.Saml2Exception;
+import org.springframework.security.saml2.core.Saml2X509Credential;
+import org.springframework.security.saml2.provider.service.metadata.OpenSamlMetadataResolver;
+import org.springframework.security.saml2.provider.service.metadata.Saml2MetadataResolver;
+import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
+import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
+import org.springframework.util.Assert;
+import org.w3c.dom.Element;
+
+import javax.xml.namespace.QName;
+import java.security.cert.CertificateEncodingException;
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.Collection;
+import java.util.List;
+import java.util.function.Consumer;
+
+/**
+ * OpenSAML 5 compatible replacement for Spring Security's {@link OpenSamlMetadataResolver}.
+ *
+ * Spring Security's {@code OpenSamlMetadataResolver} uses the OpenSAML 4 internal class
+ * {@code net.shibboleth.utilities.java.support.xml.SerializeSupport} which is not present
+ * when using OpenSAML 5. This implementation uses the OpenSAML 5 equivalent
+ * {@code net.shibboleth.shared.xml.SerializeSupport} directly.
+ */
+public final class OpenSaml5MetadataResolver implements Saml2MetadataResolver {
+
+ private Consumer entityDescriptorCustomizer = (parameters) -> {
+ };
+
+ public OpenSaml5MetadataResolver() {
+ }
+
+ @Override
+ public String resolve(RelyingPartyRegistration relyingPartyRegistration) {
+ EntityDescriptor entityDescriptor = buildEntityDescriptor(relyingPartyRegistration);
+ return serialize(entityDescriptor);
+ }
+
+ /**
+ * Set a {@link Consumer} for modifying the OpenSAML {@link EntityDescriptor}.
+ */
+ public void setEntityDescriptorCustomizer(Consumer entityDescriptorCustomizer) {
+ Assert.notNull(entityDescriptorCustomizer, "entityDescriptorCustomizer cannot be null");
+ this.entityDescriptorCustomizer = entityDescriptorCustomizer;
+ }
+
+ private EntityDescriptor buildEntityDescriptor(RelyingPartyRegistration registration) {
+ EntityDescriptor entityDescriptor = build(EntityDescriptor.DEFAULT_ELEMENT_NAME);
+ entityDescriptor.setEntityID(registration.getEntityId());
+ SPSSODescriptor spSsoDescriptor = buildSpSsoDescriptor(registration);
+ entityDescriptor.getRoleDescriptors(SPSSODescriptor.DEFAULT_ELEMENT_NAME).add(spSsoDescriptor);
+ this.entityDescriptorCustomizer.accept(
+ new OpenSamlMetadataResolver.EntityDescriptorParameters(entityDescriptor, registration));
+ return entityDescriptor;
+ }
+
+ private SPSSODescriptor buildSpSsoDescriptor(RelyingPartyRegistration registration) {
+ SPSSODescriptor spSsoDescriptor = build(SPSSODescriptor.DEFAULT_ELEMENT_NAME);
+ spSsoDescriptor.addSupportedProtocol(SAMLConstants.SAML20P_NS);
+ spSsoDescriptor.getKeyDescriptors()
+ .addAll(buildKeys(registration.getSigningX509Credentials(), UsageType.SIGNING));
+ spSsoDescriptor.getKeyDescriptors()
+ .addAll(buildKeys(registration.getDecryptionX509Credentials(), UsageType.ENCRYPTION));
+ spSsoDescriptor.getAssertionConsumerServices().add(buildAssertionConsumerService(registration));
+ if (registration.getSingleLogoutServiceLocation() != null) {
+ for (Saml2MessageBinding binding : registration.getSingleLogoutServiceBindings()) {
+ spSsoDescriptor.getSingleLogoutServices().add(buildSingleLogoutService(registration, binding));
+ }
+ }
+ if (registration.getNameIdFormat() != null) {
+ spSsoDescriptor.getNameIDFormats().add(buildNameIDFormat(registration));
+ }
+ return spSsoDescriptor;
+ }
+
+ private List buildKeys(Collection credentials, UsageType usageType) {
+ List list = new ArrayList<>();
+ for (Saml2X509Credential credential : credentials) {
+ list.add(buildKeyDescriptor(usageType, credential.getCertificate()));
+ }
+ return list;
+ }
+
+ private KeyDescriptor buildKeyDescriptor(UsageType usageType, java.security.cert.X509Certificate certificate) {
+ KeyDescriptor keyDescriptor = build(KeyDescriptor.DEFAULT_ELEMENT_NAME);
+ KeyInfo keyInfo = build(KeyInfo.DEFAULT_ELEMENT_NAME);
+ X509Certificate x509Certificate = build(X509Certificate.DEFAULT_ELEMENT_NAME);
+ X509Data x509Data = build(X509Data.DEFAULT_ELEMENT_NAME);
+ try {
+ x509Certificate.setValue(new String(Base64.getEncoder().encode(certificate.getEncoded())));
+ } catch (CertificateEncodingException ex) {
+ throw new Saml2Exception("Cannot encode certificate " + certificate);
+ }
+ x509Data.getX509Certificates().add(x509Certificate);
+ keyInfo.getX509Datas().add(x509Data);
+ keyDescriptor.setUse(usageType);
+ keyDescriptor.setKeyInfo(keyInfo);
+ return keyDescriptor;
+ }
+
+ private AssertionConsumerService buildAssertionConsumerService(RelyingPartyRegistration registration) {
+ AssertionConsumerService acs = build(AssertionConsumerService.DEFAULT_ELEMENT_NAME);
+ acs.setLocation(registration.getAssertionConsumerServiceLocation());
+ acs.setBinding(registration.getAssertionConsumerServiceBinding().getUrn());
+ acs.setIndex(1);
+ return acs;
+ }
+
+ private SingleLogoutService buildSingleLogoutService(RelyingPartyRegistration registration,
+ Saml2MessageBinding binding) {
+ SingleLogoutService slo = build(SingleLogoutService.DEFAULT_ELEMENT_NAME);
+ slo.setLocation(registration.getSingleLogoutServiceLocation());
+ slo.setResponseLocation(registration.getSingleLogoutServiceResponseLocation());
+ slo.setBinding(binding.getUrn());
+ return slo;
+ }
+
+ private NameIDFormat buildNameIDFormat(RelyingPartyRegistration registration) {
+ NameIDFormat nameIdFormat = build(NameIDFormat.DEFAULT_ELEMENT_NAME);
+ nameIdFormat.setURI(registration.getNameIdFormat());
+ return nameIdFormat;
+ }
+
+ private String serialize(XMLObject xmlObject) {
+ try {
+ Marshaller marshaller = XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(xmlObject);
+ if (marshaller == null) {
+ throw new Saml2Exception("No marshaller found for " + xmlObject.getClass().getName());
+ }
+ Element element = marshaller.marshall(xmlObject);
+ return SerializeSupport.prettyPrintXML(element);
+ } catch (MarshallingException ex) {
+ throw new Saml2Exception("Failed to serialize metadata", ex);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private T build(QName elementName) {
+ return (T) XMLObjectProviderRegistrySupport.getBuilderFactory()
+ .getBuilder(elementName)
+ .buildObject(elementName);
+ }
+}
+
diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/OpenSamlDecryptionUtils.java b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/OpenSamlDecryptionUtils.java
index b4350efdc8e..e851e2cddaf 100644
--- a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/OpenSamlDecryptionUtils.java
+++ b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/OpenSamlDecryptionUtils.java
@@ -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 more to the spring-security version of OpenSaml5AuthenticationProvider.
*
* Utility methods for decrypting SAML components with OpenSAML
*
diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/OpenSamlVerificationUtils.java b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/OpenSamlVerificationUtils.java
index 2284afb6045..642fd4ad049 100644
--- a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/OpenSamlVerificationUtils.java
+++ b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/OpenSamlVerificationUtils.java
@@ -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;
@@ -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 more to the spring-security version of OpenSaml5AuthenticationProvider.
*
* Utility methods for verifying SAML component signatures with OpenSAML
*
diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/Saml2BearerGrantAuthenticationConverter.java b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/Saml2BearerGrantAuthenticationConverter.java
index 37381cf0111..965cdbb84b4 100644
--- a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/Saml2BearerGrantAuthenticationConverter.java
+++ b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/Saml2BearerGrantAuthenticationConverter.java
@@ -17,7 +17,7 @@
package org.cloudfoundry.identity.uaa.provider.saml;
import lombok.extern.slf4j.Slf4j;
-import net.shibboleth.utilities.java.support.xml.ParserPool;
+import net.shibboleth.shared.xml.ParserPool;
import org.cloudfoundry.identity.uaa.authentication.BackwardsCompatibleTokenEndpointAuthenticationFilter;
import org.cloudfoundry.identity.uaa.zone.IdentityZone;
import org.cloudfoundry.identity.uaa.zone.beans.IdentityZoneManager;
@@ -61,7 +61,7 @@
import java.util.Optional;
import java.util.function.Consumer;
-import static org.cloudfoundry.identity.uaa.provider.saml.OpenSaml4AuthenticationProvider.createDefaultAssertionValidatorWithParameters;
+import static org.cloudfoundry.identity.uaa.provider.saml.OpenSaml5AuthenticationProvider.createDefaultAssertionValidatorWithParameters;
/**
* This {@link AuthenticationConverter} is used in the SAML2 Bearer Grant exchange in {@link BackwardsCompatibleTokenEndpointAuthenticationFilter}
@@ -89,13 +89,13 @@ public final class Saml2BearerGrantAuthenticationConverter implements Authentica
parserPool = registry.getParserPool();
}
- private final Converter assertionSignatureValidator = OpenSaml4AuthenticationProvider.createDefaultAssertionSignatureValidator();
+ private final Converter assertionSignatureValidator = OpenSaml5AuthenticationProvider.createDefaultAssertionSignatureValidator();
- private final Consumer assertionElementsDecrypter = OpenSaml4AuthenticationProvider.createDefaultAssertionElementsDecrypter();
+ private final Consumer assertionElementsDecrypter = OpenSaml5AuthenticationProvider.createDefaultAssertionElementsDecrypter();
- private final Converter assertionValidator = createDefaultAssertionValidator();
+ private final Converter assertionValidator = createDefaultAssertionValidator();
- private final Converter assertionTokenAuthenticationConverter = createDefaultAssertionAuthenticationConverter();
+ private final Converter assertionTokenAuthenticationConverter = createDefaultAssertionAuthenticationConverter();
private final RelyingPartyRegistrationResolver relyingPartyRegistrationResolver;
private final IdentityZoneManager identityZoneManager;
@@ -120,7 +120,7 @@ public Saml2BearerGrantAuthenticationConverter(RelyingPartyRegistrationResolver
*
* @return the default assertion validator strategy
*/
- public static Converter createDefaultAssertionValidator() {
+ public static Converter createDefaultAssertionValidator() {
return createDefaultAssertionValidatorWithParameters(
params -> params.put(SAML2AssertionValidationParameters.CLOCK_SKEW, Duration.ofMinutes(5)), true);
@@ -132,13 +132,13 @@ public static Converter createDefaultAssertionAuthenticationConverter() {
+ static Converter createDefaultAssertionAuthenticationConverter() {
return assertionToken -> {
Assertion assertion = assertionToken.getAssertion();
Saml2AuthenticationToken token = assertionToken.getToken();
String username = assertion.getSubject().getNameID().getValue();
- Map> attributes = OpenSaml4AuthenticationProvider.getAssertionAttributes(assertion);
- List sessionIndexes = OpenSaml4AuthenticationProvider.getSessionIndexes(assertion);
+ Map> attributes = OpenSaml5AuthenticationProvider.getAssertionAttributes(assertion);
+ List sessionIndexes = OpenSaml5AuthenticationProvider.getSessionIndexes(assertion);
DefaultSaml2AuthenticatedPrincipal principal = new DefaultSaml2AuthenticatedPrincipal(username, attributes,
sessionIndexes);
String registrationId = token.getRelyingPartyRegistration().getRegistrationId();
@@ -192,7 +192,7 @@ public Authentication authenticate(Authentication authentication) throws Authent
Assertion assertion = parseAssertion(serializedAssertion);
process(token, assertion);
AbstractAuthenticationToken authenticationResponse = this.assertionTokenAuthenticationConverter
- .convert(new OpenSaml4AuthenticationProvider.AssertionToken(assertion, token));
+ .convert(new OpenSaml5AuthenticationProvider.AssertionToken(assertion, token));
if (authenticationResponse != null) {
authenticationResponse.setDetails(authentication.getDetails());
}
@@ -200,7 +200,7 @@ public Authentication authenticate(Authentication authentication) throws Authent
} catch (Saml2AuthenticationException ex) {
throw ex;
} catch (Exception ex) {
- throw OpenSaml4AuthenticationProvider.createAuthenticationException(Saml2ErrorCodes.INTERNAL_VALIDATION_ERROR, ex.getMessage(), ex);
+ throw OpenSaml5AuthenticationProvider.createAuthenticationException(Saml2ErrorCodes.INTERNAL_VALIDATION_ERROR, ex.getMessage(), ex);
}
}
@@ -211,7 +211,7 @@ private static Assertion parseAssertion(String assertion) throws Saml2Exception,
Element element = document.getDocumentElement();
return (Assertion) assertionUnmarshaller.unmarshall(element);
} catch (Exception ex) {
- throw OpenSaml4AuthenticationProvider.createAuthenticationException(Saml2ErrorCodes.INVALID_ASSERTION, "Unable to parse bearer assertion", ex);
+ throw OpenSaml5AuthenticationProvider.createAuthenticationException(Saml2ErrorCodes.INVALID_ASSERTION, "Unable to parse bearer assertion", ex);
}
}
@@ -222,7 +222,7 @@ protected static Response parseSamlResponse(String samlResponse) throws Saml2Exc
Element element = document.getDocumentElement();
return (Response) responseUnMarshaller.unmarshall(element);
} catch (Exception ex) {
- throw OpenSaml4AuthenticationProvider.createAuthenticationException(Saml2ErrorCodes.INVALID_RESPONSE, "Unable to parse saml response", ex);
+ throw OpenSaml5AuthenticationProvider.createAuthenticationException(Saml2ErrorCodes.INVALID_RESPONSE, "Unable to parse saml response", ex);
}
}
@@ -252,14 +252,14 @@ private void process(Saml2AuthenticationToken token, Assertion assertion) {
String issuer = getIssuer(assertion);
log.debug("Processing SAML response from {}", issuer);
- OpenSaml4AuthenticationProvider.AssertionToken assertionToken = new OpenSaml4AuthenticationProvider.AssertionToken(assertion, token);
+ OpenSaml5AuthenticationProvider.AssertionToken assertionToken = new OpenSaml5AuthenticationProvider.AssertionToken(assertion, token);
Saml2ResponseValidatorResult result = this.assertionSignatureValidator.convert(assertionToken);
if (assertion.isSigned()) {
- this.assertionElementsDecrypter.accept(new OpenSaml4AuthenticationProvider.AssertionToken(assertion, token));
+ this.assertionElementsDecrypter.accept(new OpenSaml5AuthenticationProvider.AssertionToken(assertion, token));
} else if (hasEncryptedElements(assertion)) {
- this.assertionElementsDecrypter.accept(new OpenSaml4AuthenticationProvider.AssertionToken(assertion, token));
+ this.assertionElementsDecrypter.accept(new OpenSaml5AuthenticationProvider.AssertionToken(assertion, token));
} else {
- throw OpenSaml4AuthenticationProvider.createAuthenticationException(
+ throw OpenSaml5AuthenticationProvider.createAuthenticationException(
Saml2ErrorCodes.INVALID_SIGNATURE,
"Assertion is missing a signature.",
null
@@ -267,7 +267,7 @@ private void process(Saml2AuthenticationToken token, Assertion assertion) {
}
result = result.concat(this.assertionValidator.convert(assertionToken));
- if (!OpenSaml4AuthenticationProvider.hasName(assertion)) {
+ if (!OpenSaml5AuthenticationProvider.hasName(assertion)) {
Saml2Error error = new Saml2Error(Saml2ErrorCodes.SUBJECT_NOT_FOUND,
"Assertion [" + assertion.getID() + "] is missing a subject");
result = result.concat(error);
@@ -281,7 +281,7 @@ private void process(Saml2AuthenticationToken token, Assertion assertion) {
log.debug("Found {} validation errors in SAML assertion [{}}]", errors.size(), assertion.getID());
}
Saml2Error first = errors.iterator().next();
- throw OpenSaml4AuthenticationProvider.createAuthenticationException(first.getErrorCode(), first.getDescription(), null);
+ throw OpenSaml5AuthenticationProvider.createAuthenticationException(first.getErrorCode(), first.getDescription(), null);
} else {
log.debug("Successfully processed SAML Assertion [{}]", assertion.getID());
}
diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/Saml2Utils.java b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/Saml2Utils.java
index 076fd35fb73..8fc3b2d0780 100644
--- a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/Saml2Utils.java
+++ b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/Saml2Utils.java
@@ -59,7 +59,7 @@ public static byte[] samlBearerDecode(String s) {
try {
return Base64.getUrlDecoder().decode(s);
} catch (IllegalArgumentException ex) {
- throw OpenSaml4AuthenticationProvider.createAuthenticationException(Saml2ErrorCodes.INVALID_ASSERTION, "Unable to urlBase64Decode bearer assertion", ex);
+ throw OpenSaml5AuthenticationProvider.createAuthenticationException(Saml2ErrorCodes.INVALID_ASSERTION, "Unable to urlBase64Decode bearer assertion", ex);
}
}
diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/SamlAuthenticationFilterConfig.java b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/SamlAuthenticationFilterConfig.java
index bdd1aa99886..a9ee8cb7de8 100644
--- a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/SamlAuthenticationFilterConfig.java
+++ b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/SamlAuthenticationFilterConfig.java
@@ -22,10 +22,10 @@
import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver;
import org.springframework.security.saml2.provider.service.web.Saml2AuthenticationTokenConverter;
import org.springframework.security.saml2.provider.service.web.Saml2WebSsoAuthenticationRequestFilter;
-import org.springframework.security.saml2.provider.service.web.authentication.OpenSaml4AuthenticationRequestResolver;
+import org.springframework.security.saml2.provider.service.web.authentication.OpenSaml5AuthenticationRequestResolver;
import org.springframework.security.saml2.provider.service.web.authentication.Saml2WebSsoAuthenticationFilter;
-import org.springframework.security.saml2.provider.service.web.authentication.logout.OpenSaml4LogoutRequestResolver;
-import org.springframework.security.saml2.provider.service.web.authentication.logout.OpenSaml4LogoutResponseResolver;
+import org.springframework.security.saml2.provider.service.web.authentication.logout.OpenSaml5LogoutRequestResolver;
+import org.springframework.security.saml2.provider.service.web.authentication.logout.OpenSaml5LogoutResponseResolver;
import org.springframework.security.saml2.provider.service.web.authentication.logout.Saml2LogoutRequestFilter;
import org.springframework.security.saml2.provider.service.web.authentication.logout.Saml2LogoutRequestResolver;
import org.springframework.security.saml2.provider.service.web.authentication.logout.Saml2LogoutResponseFilter;
@@ -53,9 +53,9 @@ public class SamlAuthenticationFilterConfig {
*/
@Bean
FilterRegistrationBean saml2WebSsoAuthenticationRequestFilter(RelyingPartyRegistrationResolver relyingPartyRegistrationResolver) {
- OpenSaml4AuthenticationRequestResolver openSaml4AuthenticationRequestResolver = new OpenSaml4AuthenticationRequestResolver(relyingPartyRegistrationResolver);
+ OpenSaml5AuthenticationRequestResolver openSaml5AuthenticationRequestResolver = new OpenSaml5AuthenticationRequestResolver(relyingPartyRegistrationResolver);
- Saml2WebSsoAuthenticationRequestFilter filter = new Saml2WebSsoAuthenticationRequestFilter(openSaml4AuthenticationRequestResolver);
+ Saml2WebSsoAuthenticationRequestFilter filter = new Saml2WebSsoAuthenticationRequestFilter(openSaml5AuthenticationRequestResolver);
FilterRegistrationBean bean = new FilterRegistrationBean<>(filter);
bean.setEnabled(false);
return bean;
@@ -93,12 +93,12 @@ AuthenticationProvider samlAuthenticationProvider(IdentityZoneManager identityZo
new SamlUaaResponseAuthenticationConverter(identityZoneManager, samlUaaAuthenticationUserManager);
samlResponseAuthenticationConverter.setApplicationEventPublisher(applicationEventPublisher);
- OpenSaml4AuthenticationProvider samlResponseAuthenticationProvider = new OpenSaml4AuthenticationProvider();
+ OpenSaml5AuthenticationProvider samlResponseAuthenticationProvider = new OpenSaml5AuthenticationProvider();
samlResponseAuthenticationProvider.setResponseAuthenticationConverter(samlResponseAuthenticationConverter);
// This validator ignores wraps the default validator and ignores InResponseTo errors, if configured
UaaInResponseToHandlingResponseValidator uaaInResponseToHandlingResponseValidator =
- new UaaInResponseToHandlingResponseValidator(OpenSaml4AuthenticationProvider.createDefaultResponseValidator(), samlConfigProps.getDisableInResponseToCheck());
+ new UaaInResponseToHandlingResponseValidator(OpenSaml5AuthenticationProvider.createDefaultResponseValidator(), samlConfigProps.getDisableInResponseToCheck());
samlResponseAuthenticationProvider.setResponseValidator(uaaInResponseToHandlingResponseValidator);
return samlResponseAuthenticationProvider;
@@ -149,7 +149,7 @@ public UaaSavedRequestAwareAuthenticationSuccessHandler successRedirectHandler()
@Bean
Saml2LogoutRequestResolver saml2LogoutRequestResolver(RelyingPartyRegistrationResolver relyingPartyRegistrationResolver) {
- OpenSaml4LogoutRequestResolver logoutRequestResolver = new OpenSaml4LogoutRequestResolver(relyingPartyRegistrationResolver);
+ OpenSaml5LogoutRequestResolver logoutRequestResolver = new OpenSaml5LogoutRequestResolver(relyingPartyRegistrationResolver);
logoutRequestResolver.setParametersConsumer((parameters) -> {
LogoutRequest logoutRequest = parameters.getLogoutRequest();
NameID nameId = logoutRequest.getNameID();
@@ -195,7 +195,7 @@ FilterRegistrationBean saml2LogoutRequestFilter(UaaRel
// This validator ignores missing signatures in the SAML2 Logout Response
Saml2LogoutRequestValidator logoutRequestValidator = new SamlLogoutRequestValidator();
- Saml2LogoutResponseResolver logoutResponseResolver = new OpenSaml4LogoutResponseResolver(relyingPartyRegistrationResolver);
+ Saml2LogoutResponseResolver logoutResponseResolver = new OpenSaml5LogoutResponseResolver(relyingPartyRegistrationResolver);
SecurityContextLogoutHandler securityContextLogoutHandlerWithHandler = new SecurityContextLogoutHandler();
CsrfLogoutHandler csrfLogoutHandler = new CsrfLogoutHandler(loginCookieCsrfRepository);
diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/SamlConfiguration.java b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/SamlConfiguration.java
index c4bf6903fb9..e7a278e6827 100644
--- a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/SamlConfiguration.java
+++ b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/SamlConfiguration.java
@@ -11,6 +11,7 @@
import org.opensaml.core.config.ConfigurationService;
import org.opensaml.core.config.InitializationException;
import org.opensaml.core.config.Initializer;
+import org.opensaml.core.config.provider.PropertiesAdapter;
import org.opensaml.security.config.GlobalNamedCurveRegistryInitializer;
import org.opensaml.xmlsec.config.impl.DefaultSecurityConfigurationBootstrap;
import org.springframework.beans.factory.annotation.Qualifier;
@@ -74,10 +75,13 @@ public class SamlConfiguration {
@Bean
public static Boolean setupOpenSaml() {
if (samlInitialized.compareAndSet(false, true)) {
- Properties props = ConfigurationService.getConfigurationProperties();
- props.put(CONFIG_PROPERTY_ECDH_DEFAULT_KDF, DefaultSecurityConfigurationBootstrap.PBKDF2);
+ Properties props = new Properties();
+ props.setProperty(CONFIG_PROPERTY_ECDH_DEFAULT_KDF, DefaultSecurityConfigurationBootstrap.PBKDF2);
+ ConfigurationService.setDefaultConfigurationPropertiesSource(() -> new PropertiesAdapter(props));
Class> toSkip = GlobalNamedCurveRegistryInitializer.class;
- ServiceLoader.load(Initializer.class).stream().filter((provider) -> provider.type() != toSkip).forEach((provider) -> init(provider));
+ ServiceLoader.load(Initializer.class).stream()
+ .filter(provider -> provider.type() != toSkip)
+ .forEach(SamlConfiguration::init);
try {
OpenSamlInitializationService.initialize();
} catch (NoClassDefFoundError | NoSuchMethodError e) {
diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/SamlMetadataEndpoint.java b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/SamlMetadataEndpoint.java
index b37588c1acd..a143c422557 100644
--- a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/SamlMetadataEndpoint.java
+++ b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/SamlMetadataEndpoint.java
@@ -6,7 +6,6 @@
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
-import org.springframework.security.saml2.provider.service.metadata.OpenSamlMetadataResolver;
import org.springframework.security.saml2.provider.service.metadata.Saml2MetadataResolver;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver;
@@ -34,7 +33,7 @@ public SamlMetadataEndpoint(RelyingPartyRegistrationResolver registrationResolve
@Qualifier("signSamlMetaData") boolean signMetaData) {
Assert.notNull(registrationResolver, "registrationResolver cannot be null");
relyingPartyRegistrationResolver = registrationResolver;
- OpenSamlMetadataResolver metadataResolver = new OpenSamlMetadataResolver();
+ OpenSaml5MetadataResolver metadataResolver = new OpenSaml5MetadataResolver();
saml2MetadataResolver = metadataResolver;
metadataResolver.setEntityDescriptorCustomizer(
new SamlMetadataEntityDescriptorCustomizer(identityZoneManager, signatureAlgorithms, signMetaData));
diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/SamlMetadataEntityDescriptorCustomizer.java b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/SamlMetadataEntityDescriptorCustomizer.java
index 8e9e564f663..7f96b156204 100644
--- a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/SamlMetadataEntityDescriptorCustomizer.java
+++ b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/SamlMetadataEntityDescriptorCustomizer.java
@@ -2,7 +2,7 @@
import lombok.Value;
import lombok.extern.slf4j.Slf4j;
-import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
+import net.shibboleth.shared.resolver.CriteriaSet;
import org.cloudfoundry.identity.uaa.zone.SamlConfig;
import org.cloudfoundry.identity.uaa.zone.beans.IdentityZoneManager;
import org.opensaml.core.xml.XMLObjectBuilder;
diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/SamlUaaResponseAuthenticationConverter.java b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/SamlUaaResponseAuthenticationConverter.java
index 18c02a62e29..44ab2caba26 100644
--- a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/SamlUaaResponseAuthenticationConverter.java
+++ b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/SamlUaaResponseAuthenticationConverter.java
@@ -26,7 +26,7 @@
@Slf4j
@Getter
public class SamlUaaResponseAuthenticationConverter
- implements Converter,
+ implements Converter,
ApplicationEventPublisherAware {
private final IdentityZoneManager identityZoneManager;
@@ -42,7 +42,7 @@ public SamlUaaResponseAuthenticationConverter(IdentityZoneManager identityZoneMa
}
@Override
- public UaaAuthentication convert(OpenSaml4AuthenticationProvider.ResponseToken responseToken) {
+ public UaaAuthentication convert(OpenSaml5AuthenticationProvider.ResponseToken responseToken) {
Saml2AuthenticationToken authenticationToken = responseToken.getToken();
Response response = responseToken.getResponse();
List assertions = response.getAssertions();
diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/UaaInResponseToHandlingResponseValidator.java b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/UaaInResponseToHandlingResponseValidator.java
index e1374883518..e2cba71ee16 100644
--- a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/UaaInResponseToHandlingResponseValidator.java
+++ b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/UaaInResponseToHandlingResponseValidator.java
@@ -39,19 +39,19 @@
* The InResponseTo attribute is optional, but if it is present, the default validator checks against the ID of the request.
*/
@Slf4j
-public final class UaaInResponseToHandlingResponseValidator implements Converter {
+public final class UaaInResponseToHandlingResponseValidator implements Converter {
private final boolean uaaWideDisableInResponseToCheck;
- private final Converter delegate;
+ private final Converter delegate;
- public UaaInResponseToHandlingResponseValidator(Converter delegate,
+ public UaaInResponseToHandlingResponseValidator(Converter delegate,
boolean uaaWideDisableInResponseToCheck) {
this.delegate = delegate;
this.uaaWideDisableInResponseToCheck = uaaWideDisableInResponseToCheck;
}
@Override
- public Saml2ResponseValidatorResult convert(@NonNull OpenSaml4AuthenticationProvider.ResponseToken source) {
+ public Saml2ResponseValidatorResult convert(@NonNull OpenSaml5AuthenticationProvider.ResponseToken source) {
Saml2ResponseValidatorResult result = delegate.convert(source);
// if the result is successful, return it
if (result == null || !result.hasErrors()) {
diff --git a/server/src/test/java/org/cloudfoundry/identity/uaa/provider/saml/OpenSaml4AuthenticationProviderUaaTests.java b/server/src/test/java/org/cloudfoundry/identity/uaa/provider/saml/OpenSaml5AuthenticationProviderUaaTests.java
similarity index 99%
rename from server/src/test/java/org/cloudfoundry/identity/uaa/provider/saml/OpenSaml4AuthenticationProviderUaaTests.java
rename to server/src/test/java/org/cloudfoundry/identity/uaa/provider/saml/OpenSaml5AuthenticationProviderUaaTests.java
index 1f654be1ee2..7e0812a010e 100644
--- a/server/src/test/java/org/cloudfoundry/identity/uaa/provider/saml/OpenSaml4AuthenticationProviderUaaTests.java
+++ b/server/src/test/java/org/cloudfoundry/identity/uaa/provider/saml/OpenSaml5AuthenticationProviderUaaTests.java
@@ -105,7 +105,7 @@
import static org.mockito.Mockito.when;
@WithDatabaseContext
-class OpenSaml4AuthenticationProviderUaaTests {
+class OpenSaml5AuthenticationProviderUaaTests {
private static final String SAML_USER = "saml.user";
private static final String SAML_ADMIN = "saml.admin";
@@ -122,7 +122,7 @@ class OpenSaml4AuthenticationProviderUaaTests {
private static final String JOHN_THE_SLOTH = "John the Sloth";
private static final String KARI_THE_ANT_EATER = "Kari the Ant Eater";
private static final String IDP_META_DATA = getResourceAsString(
- OpenSaml4AuthenticationProviderUaaTests.class, "IDP_META_DATA.xml");
+ OpenSaml5AuthenticationProviderUaaTests.class, "IDP_META_DATA.xml");
private static final String TEST_EMAIL = "john.doe@example.com";
private static final String TEST_USERNAME = "test@saml.user";
diff --git a/server/src/test/java/org/cloudfoundry/identity/uaa/provider/saml/OpenSaml4AuthenticationProviderUnitTests.java b/server/src/test/java/org/cloudfoundry/identity/uaa/provider/saml/OpenSaml5AuthenticationProviderUnitTests.java
similarity index 97%
rename from server/src/test/java/org/cloudfoundry/identity/uaa/provider/saml/OpenSaml4AuthenticationProviderUnitTests.java
rename to server/src/test/java/org/cloudfoundry/identity/uaa/provider/saml/OpenSaml5AuthenticationProviderUnitTests.java
index 41b861f109f..ff331780643 100644
--- a/server/src/test/java/org/cloudfoundry/identity/uaa/provider/saml/OpenSaml4AuthenticationProviderUnitTests.java
+++ b/server/src/test/java/org/cloudfoundry/identity/uaa/provider/saml/OpenSaml5AuthenticationProviderUnitTests.java
@@ -1,8 +1,8 @@
package org.cloudfoundry.identity.uaa.provider.saml;
import com.fasterxml.jackson.databind.ObjectMapper;
-import net.shibboleth.utilities.java.support.xml.SerializeSupport;
-import org.cloudfoundry.identity.uaa.provider.saml.OpenSaml4AuthenticationProvider.ResponseToken;
+import net.shibboleth.shared.xml.SerializeSupport;
+import org.cloudfoundry.identity.uaa.provider.saml.OpenSaml5AuthenticationProvider.ResponseToken;
import org.cloudfoundry.identity.uaa.zone.IdentityZone;
import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder;
import org.junit.jupiter.api.AfterEach;
@@ -70,21 +70,21 @@
import static org.mockito.Mockito.verify;
/**
- * This was copied from Spring Security, Test Classes and modified to work with the modified OpenSaml4AuthenticationProvider.
+ * This was copied from Spring Security, Test Classes and modified to work with the modified OpenSaml5AuthenticationProvider.
*
- * Once we can move to the spring-security version of OpenSaml4AuthenticationProvider,
+ * Once we can move to the spring-security version of OpenSaml5AuthenticationProvider,
* this class should be removed, along with OpenSamlDecryptionUtils and OpenSamlVerificationUtils.
*
* Modified Tests:
* authenticateWhenAssertionContainsAttributesThenItSucceeds
* deserializeWhenAssertionContainsAttributesThenWorks
*
- * Tests for {@link OpenSaml4AuthenticationProvider}
+ * Tests for {@link OpenSaml5AuthenticationProvider}
*
* @author Filip Hanik
* @author Josh Cummings
*/
-class OpenSaml4AuthenticationProviderUnitTests {
+class OpenSaml5AuthenticationProviderUnitTests {
private static final String DESTINATION = "http://localhost:8080/uaa/saml/SSO/alias/integration-saml-entity-id";
@@ -92,7 +92,8 @@ class OpenSaml4AuthenticationProviderUnitTests {
private static final String ASSERTING_PARTY_ENTITY_ID = "https://some.idp.test/saml2/idp";
- private final OpenSaml4AuthenticationProvider provider = new OpenSaml4AuthenticationProvider();
+ private final OpenSaml5AuthenticationProvider provider = new OpenSaml5AuthenticationProvider();
+
@BeforeEach
void setUp() {
@@ -106,14 +107,14 @@ void setUp() {
@Test
void supportsWhenSaml2AuthenticationTokenThenReturnTrue() {
assertThat(this.provider.supports(Saml2AuthenticationToken.class))
- .withFailMessage(OpenSaml4AuthenticationProvider.class + "should support " + Saml2AuthenticationToken.class)
+ .withFailMessage(OpenSaml5AuthenticationProvider.class + "should support " + Saml2AuthenticationToken.class)
.isTrue();
}
@Test
void supportsWhenNotSaml2AuthenticationTokenThenReturnFalse() {
assertThat(this.provider.supports(Authentication.class))
- .withFailMessage(OpenSaml4AuthenticationProvider.class + "should not support " + Authentication.class)
+ .withFailMessage(OpenSaml5AuthenticationProvider.class + "should not support " + Authentication.class)
.isFalse();
}
@@ -670,10 +671,10 @@ void writeObjectWhenTypeIsSaml2AuthenticationThenNoException() throws IOExceptio
void createDefaultAssertionValidatorWhenAssertionThenValidates() {
Response response = TestOpenSamlObjects.signedResponseWithOneAssertion();
Assertion assertion = response.getAssertions().getFirst();
- OpenSaml4AuthenticationProvider.AssertionToken assertionToken = new OpenSaml4AuthenticationProvider.AssertionToken(
+ OpenSaml5AuthenticationProvider.AssertionToken assertionToken = new OpenSaml5AuthenticationProvider.AssertionToken(
assertion, token());
assertThat(
- OpenSaml4AuthenticationProvider.createDefaultAssertionValidator().convert(assertionToken).hasErrors())
+ OpenSaml5AuthenticationProvider.createDefaultAssertionValidator().convert(assertionToken).hasErrors())
.isFalse();
}
@@ -693,7 +694,7 @@ void createDefaultResponseAuthenticationConverterWhenResponseThenConverts() {
Response response = TestOpenSamlObjects.signedResponseWithOneAssertion();
Saml2AuthenticationToken token = token(response, verifying(registration()));
ResponseToken responseToken = new ResponseToken(response, token);
- Saml2Authentication authentication = OpenSaml4AuthenticationProvider
+ Saml2Authentication authentication = OpenSaml5AuthenticationProvider
.createDefaultResponseAuthenticationConverter()
.convert(responseToken);
assertThat(authentication.getName()).isEqualTo("test@saml.user");
@@ -745,7 +746,7 @@ void setResponseValidatorWhenNullThenIllegalArgument() {
void authenticateWhenCustomResponseValidatorThenUses() {
Converter validator = mock(Converter.class);
// @formatter:off
- provider.setResponseValidator(responseToken -> OpenSaml4AuthenticationProvider.createDefaultResponseValidator()
+ provider.setResponseValidator(responseToken -> OpenSaml5AuthenticationProvider.createDefaultResponseValidator()
.convert(responseToken)
.concat(validator.convert(responseToken))
);
@@ -774,7 +775,7 @@ void authenticateWhenAssertionIssuerNotValidThenFailsWithInvalidIssuer() {
// gh-14931
@Test
void authenticateWhenAssertionHasProxyRestrictionThenParses() {
- OpenSaml4AuthenticationProvider provider = new OpenSaml4AuthenticationProvider();
+ OpenSaml5AuthenticationProvider provider = new OpenSaml5AuthenticationProvider();
Response response = response();
Assertion assertion = assertion();
ProxyRestriction condition = new ProxyRestrictionBuilder().buildObject();
@@ -905,15 +906,13 @@ private AbstractSaml2AuthenticationRequest mockedStoredAuthenticationRequest(Str
}
private RelyingPartyRegistration.Builder registration() {
- return TestRelyingPartyRegistrations.noCredentials()
- .entityId(RELYING_PARTY_ENTITY_ID)
- .assertionConsumerServiceLocation(DESTINATION)
- .assertingPartyDetails(party -> party.entityId(ASSERTING_PARTY_ENTITY_ID));
+ return TestRelyingPartyRegistrations.noCredentials().entityId(RELYING_PARTY_ENTITY_ID).assertionConsumerServiceLocation(DESTINATION)
+ .assertingPartyMetadata(party -> party.entityId(ASSERTING_PARTY_ENTITY_ID));
}
private RelyingPartyRegistration.Builder verifying(RelyingPartyRegistration.Builder builder) {
- return builder.assertingPartyDetails(party -> party
- .verificationX509Credentials(c -> c.add(TestSaml2X509Credentials.relyingPartyVerifyingCredential())));
+ return builder.assertingPartyMetadata(
+ party -> party.verificationX509Credentials(c -> c.add(TestSaml2X509Credentials.relyingPartyVerifyingCredential())));
}
private RelyingPartyRegistration.Builder decrypting(RelyingPartyRegistration.Builder builder) {
diff --git a/server/src/test/java/org/cloudfoundry/identity/uaa/provider/saml/Saml2BearerGrantAuthenticationConverterTest.java b/server/src/test/java/org/cloudfoundry/identity/uaa/provider/saml/Saml2BearerGrantAuthenticationConverterTest.java
index 7da9cb13ae8..48faaf791f4 100644
--- a/server/src/test/java/org/cloudfoundry/identity/uaa/provider/saml/Saml2BearerGrantAuthenticationConverterTest.java
+++ b/server/src/test/java/org/cloudfoundry/identity/uaa/provider/saml/Saml2BearerGrantAuthenticationConverterTest.java
@@ -1,7 +1,7 @@
package org.cloudfoundry.identity.uaa.provider.saml;
import com.fasterxml.jackson.databind.ObjectMapper;
-import net.shibboleth.utilities.java.support.xml.SerializeSupport;
+import net.shibboleth.shared.xml.SerializeSupport;
import org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider;
import org.cloudfoundry.identity.uaa.impl.config.RestTemplateConfig;
import org.cloudfoundry.identity.uaa.provider.JdbcIdentityProviderProvisioning;
@@ -396,7 +396,7 @@ void writeObjectWhenTypeIsSaml2AuthenticationThenNoException() throws IOExceptio
@Test
void createDefaultAssertionValidatorWhenAssertionThenValidates() {
Assertion assertion = signed(assertion());
- OpenSaml4AuthenticationProvider.AssertionToken assertionToken = new OpenSaml4AuthenticationProvider.AssertionToken(
+ OpenSaml5AuthenticationProvider.AssertionToken assertionToken = new OpenSaml5AuthenticationProvider.AssertionToken(
assertion, token());
assertThat(
Saml2BearerGrantAuthenticationConverter.createDefaultAssertionValidator().convert(assertionToken).hasErrors())
@@ -417,7 +417,7 @@ void authenticateWithSHA1SignatureThenItSucceeds() throws Exception {
void createDefaultResponseAuthenticationConverterWhenResponseThenConverts() {
Assertion assertion = assertion();
Saml2AuthenticationToken token = token(assertion, verifying(registration()));
- OpenSaml4AuthenticationProvider.AssertionToken assertionToken = new OpenSaml4AuthenticationProvider.AssertionToken(assertion, token);
+ OpenSaml5AuthenticationProvider.AssertionToken assertionToken = new OpenSaml5AuthenticationProvider.AssertionToken(assertion, token);
AbstractAuthenticationToken authentication = Saml2BearerGrantAuthenticationConverter
.createDefaultAssertionAuthenticationConverter()
.convert(assertionToken);
diff --git a/server/src/test/java/org/cloudfoundry/identity/uaa/provider/saml/Saml2TestUtils.java b/server/src/test/java/org/cloudfoundry/identity/uaa/provider/saml/Saml2TestUtils.java
index 6a6cf8cf467..3491faf7f30 100644
--- a/server/src/test/java/org/cloudfoundry/identity/uaa/provider/saml/Saml2TestUtils.java
+++ b/server/src/test/java/org/cloudfoundry/identity/uaa/provider/saml/Saml2TestUtils.java
@@ -16,7 +16,7 @@
package org.cloudfoundry.identity.uaa.provider.saml;
-import net.shibboleth.utilities.java.support.xml.SerializeSupport;
+import net.shibboleth.shared.xml.SerializeSupport;
import org.cloudfoundry.identity.uaa.saml.SamlKey;
import org.opensaml.core.xml.XMLObject;
import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
diff --git a/server/src/test/java/org/cloudfoundry/identity/uaa/provider/saml/SamlMetadataEndpointKeyRotationTests.java b/server/src/test/java/org/cloudfoundry/identity/uaa/provider/saml/SamlMetadataEndpointKeyRotationTests.java
index 46cdf9c73f9..92ab4c38d78 100644
--- a/server/src/test/java/org/cloudfoundry/identity/uaa/provider/saml/SamlMetadataEndpointKeyRotationTests.java
+++ b/server/src/test/java/org/cloudfoundry/identity/uaa/provider/saml/SamlMetadataEndpointKeyRotationTests.java
@@ -1,6 +1,5 @@
package org.cloudfoundry.identity.uaa.provider.saml;
-import org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider;
import org.cloudfoundry.identity.uaa.zone.IdentityZone;
import org.cloudfoundry.identity.uaa.zone.IdentityZoneConfiguration;
import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder;
@@ -18,7 +17,6 @@
import org.xmlunit.assertj.MultipleNodeAssert;
import org.xmlunit.assertj.XmlAssert;
-import java.security.Security;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@@ -51,7 +49,7 @@ public class SamlMetadataEndpointKeyRotationTests {
@BeforeAll
static void beforeAll() {
- Security.addProvider(new BouncyCastleFipsProvider());
+ SamlConfiguration.setupOpenSaml();
SamlConfigProps samlConfigProps = new SamlConfigProps();
samlConfigProps.setKeys(Map.of(legacyKeyName(), legacySamlKey()));
diff --git a/server/src/test/java/org/cloudfoundry/identity/uaa/provider/saml/TestCustomOpenSamlObjects.java b/server/src/test/java/org/cloudfoundry/identity/uaa/provider/saml/TestCustomOpenSamlObjects.java
index 07574b620b0..bc6bd2b6247 100644
--- a/server/src/test/java/org/cloudfoundry/identity/uaa/provider/saml/TestCustomOpenSamlObjects.java
+++ b/server/src/test/java/org/cloudfoundry/identity/uaa/provider/saml/TestCustomOpenSamlObjects.java
@@ -23,7 +23,7 @@
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
-import net.shibboleth.utilities.java.support.xml.ElementSupport;
+import net.shibboleth.shared.xml.ElementSupport;
import org.opensaml.core.xml.AbstractXMLObject;
import org.opensaml.core.xml.AbstractXMLObjectBuilder;
import org.opensaml.core.xml.ElementExtensibleXMLObject;
@@ -43,7 +43,7 @@
/**
* This was copied from Spring Security Test Classes
*
- * Once we can move to the spring-security version of OpenSaml4AuthenticationProvider,
+ * Once we can move to the spring-security version of OpenSaml5AuthenticationProvider,
* this class should be removed.
*/
public final class TestCustomOpenSamlObjects {
@@ -202,7 +202,7 @@ public CustomSamlObjectUnmarshaller() {
protected void processChildElement(@Nonnull XMLObject parentXMLObject, @Nonnull XMLObject childXMLObject)
throws UnmarshallingException {
final CustomOpenSamlObject customSamlObject = (CustomOpenSamlObject) parentXMLObject;
- super.processChildElement(customSamlObject, childXMLObject);
+ // Do not call super - it throws UnmarshallingException in strict mode for unknown children
customSamlObject.getUnknownXMLObjects().add(childXMLObject);
}
diff --git a/server/src/test/java/org/cloudfoundry/identity/uaa/provider/saml/UaaInResponseToHandlingResponseValidatorTest.java b/server/src/test/java/org/cloudfoundry/identity/uaa/provider/saml/UaaInResponseToHandlingResponseValidatorTest.java
index 81805f6f3da..ed27b82f619 100644
--- a/server/src/test/java/org/cloudfoundry/identity/uaa/provider/saml/UaaInResponseToHandlingResponseValidatorTest.java
+++ b/server/src/test/java/org/cloudfoundry/identity/uaa/provider/saml/UaaInResponseToHandlingResponseValidatorTest.java
@@ -21,10 +21,10 @@
class UaaInResponseToHandlingResponseValidatorTest {
@Mock
- Converter delegate;
+ Converter delegate;
@Mock
- OpenSaml4AuthenticationProvider.ResponseToken responseToken;
+ OpenSaml5AuthenticationProvider.ResponseToken responseToken;
@BeforeEach
void beforeEach() {