1
0
mirror of synced 2026-05-22 13:23:17 +00:00

Add Nullability to opensaml5Main Source Set

Issue gh-17823

Signed-off-by: Josh Cummings <3627351+jzheaux@users.noreply.github.com>
This commit is contained in:
Josh Cummings
2026-02-05 13:12:33 -07:00
parent 0eba9de7d4
commit 818a7831dd
22 changed files with 291 additions and 111 deletions
@@ -138,6 +138,10 @@ javadoc {
source = sourceSets.main.allJava + sourceSets.opensaml5Main.allJava
}
tasks.named("compileOpensaml5MainJava") {
options.nullability.checking = "main"
}
tasks.register("opensaml5Test", Test) {
useJUnitPlatform()
testClassesDirs = sourceSets.opensaml5Test.output.classesDirs
@@ -118,7 +118,7 @@ class BaseOpenSamlAssertingPartyMetadataRepository implements AssertingPartyMeta
return OpenSamlAssertingPartyDetails.withEntityDescriptor(descriptor).build();
}
private EntityDescriptor resolveSingle(EntityIdCriterion criterion) {
private @Nullable EntityDescriptor resolveSingle(EntityIdCriterion criterion) {
try {
return this.metadataResolver.resolveSingle(criterion);
}
@@ -147,7 +147,7 @@ class BaseOpenSamlAssertingPartyMetadataRepository implements AssertingPartyMeta
this.metadataResolver = metadataResolver;
}
abstract EntityDescriptor resolveSingle(EntityIdCriterion entityId) throws Exception;
abstract @Nullable EntityDescriptor resolveSingle(EntityIdCriterion entityId) throws Exception;
abstract Iterable<EntityDescriptor> resolve(EntityRoleCriterion role) throws Exception;
@@ -34,9 +34,12 @@ import java.util.Set;
import javax.xml.namespace.QName;
import net.shibboleth.shared.resolver.CriteriaSet;
import net.shibboleth.shared.xml.ParserPool;
import net.shibboleth.shared.xml.SerializeSupport;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import org.opensaml.core.criterion.EntityIdCriterion;
import org.opensaml.core.xml.XMLObject;
import org.opensaml.core.xml.XMLObjectBuilder;
@@ -117,6 +120,7 @@ import org.springframework.web.util.UriUtils;
/**
* For internal use only. Subject to breaking changes at any time.
*/
@NullMarked
final class OpenSaml5Template implements OpenSamlOperations {
private static final Log logger = LogFactory.getLog(OpenSaml5Template.class);
@@ -138,7 +142,9 @@ final class OpenSaml5Template implements OpenSamlOperations {
@Override
public <T extends XMLObject> T deserialize(InputStream serialized) {
try {
Document document = XMLObjectProviderRegistrySupport.getParserPool().parse(serialized);
ParserPool pool = XMLObjectProviderRegistrySupport.getParserPool();
Assert.notNull(pool, "ParserPool must be configured");
Document document = pool.parse(serialized);
Element element = document.getDocumentElement();
UnmarshallerFactory factory = XMLObjectProviderRegistrySupport.getUnmarshallerFactory();
Unmarshaller unmarshaller = factory.getUnmarshaller(element);
@@ -158,6 +164,7 @@ final class OpenSaml5Template implements OpenSamlOperations {
@Override
public OpenSaml5SerializationConfigurer serialize(XMLObject object) {
Marshaller marshaller = XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(object);
Assert.notNull(marshaller, "Marshaller for " + object.getElementQName() + " must be configured");
try {
return serialize(marshaller.marshall(object));
}
@@ -252,7 +259,9 @@ final class OpenSaml5Template implements OpenSamlOperations {
SignatureSigningParameters parameters = resolveSigningParameters();
this.components.putAll(params);
Credential credential = parameters.getSigningCredential();
Assert.notNull(credential, "credential cannot be null when signing a SAML payload");
String algorithmUri = parameters.getSignatureAlgorithm();
Assert.notNull(algorithmUri, "algorithmUri cannot be null when signing a SAML payload");
this.components.put(Saml2ParameterNames.SIG_ALG, algorithmUri);
UriComponentsBuilder builder = UriComponentsBuilder.newInstance();
for (Map.Entry<String, String> component : this.components.entrySet()) {
@@ -328,14 +337,14 @@ final class OpenSaml5Template implements OpenSamlOperations {
private final Collection<Saml2X509Credential> credentials;
private String entityId;
private @Nullable String entityId;
OpenSaml5VerificationConfigurer(Collection<Saml2X509Credential> credentials) {
this.credentials = credentials;
}
@Override
public VerificationConfigurer entityId(String entityId) {
public VerificationConfigurer entityId(@Nullable String entityId) {
this.entityId = entityId;
return this;
}
@@ -354,6 +363,7 @@ final class OpenSaml5Template implements OpenSamlOperations {
}
private CriteriaSet verificationCriteria(Issuer issuer) {
Assert.notNull(issuer.getValue(), "required elements must have a value");
return new CriteriaSet(new EvaluableEntityIDCredentialCriterion(new EntityIdCriterion(issuer.getValue())),
new EvaluableProtocolRoleDescriptorCriterion(new ProtocolCriterion(SAMLConstants.SAML20P_NS)),
new EvaluableUsageCredentialCriterion(new UsageCriterion(UsageType.SIGNING)));
@@ -362,12 +372,21 @@ final class OpenSaml5Template implements OpenSamlOperations {
@Override
public Collection<Saml2Error> verify(SignableXMLObject signable) {
if (signable instanceof StatusResponseType response) {
Assert.notNull(response.getID(), "Response#ID cannot be null");
Assert.notNull(response.getIssuer(), "Response#Issuer cannot be null");
Assert.notNull(response.getSignature(), "Response#Signature cannot be null");
return verifySignature(response.getID(), response.getIssuer(), response.getSignature());
}
if (signable instanceof RequestAbstractType request) {
Assert.notNull(request.getID(), "Request#ID cannot be null");
Assert.notNull(request.getIssuer(), "Request#Issuer cannot be null");
Assert.notNull(request.getSignature(), "Request#Signature cannot be null");
return verifySignature(request.getID(), request.getIssuer(), request.getSignature());
}
if (signable instanceof Assertion assertion) {
Assert.notNull(assertion.getID(), "Assertion#ID cannot be null");
Assert.notNull(assertion.getIssuer(), "Assertion#Issuer cannot be null");
Assert.notNull(assertion.getSignature(), "Assertion#Signature cannot be null");
return verifySignature(assertion.getID(), assertion.getIssuer(), assertion.getSignature());
}
throw new Saml2Exception("Unsupported object of type: " + signable.getClass().getName());
@@ -408,15 +427,15 @@ final class OpenSaml5Template implements OpenSamlOperations {
return Collections.singletonList(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE,
"Missing signature algorithm for object [" + parameters.getId() + "]"));
}
if (!parameters.hasSignature()) {
byte[] signature = parameters.getSignature();
if (signature == null) {
return Collections.singletonList(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE,
"Missing signature for object [" + parameters.getId() + "]"));
}
Collection<Saml2Error> errors = new ArrayList<>();
String algorithmUri = parameters.getAlgorithm();
try {
if (!trustEngine.validate(parameters.getSignature(), parameters.getContent(), algorithmUri, criteria,
null)) {
if (!trustEngine.validate(signature, parameters.getContent(), algorithmUri, criteria, null)) {
errors.add(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE,
"Invalid signature for object [" + parameters.getId() + "]"));
}
@@ -558,7 +577,7 @@ final class OpenSaml5Template implements OpenSamlOperations {
statement.getAttributes().addAll(decrypteds);
}
private void decryptSubject(Subject subject) {
private void decryptSubject(@Nullable Subject subject) {
if (subject != null) {
if (subject.getEncryptedID() != null) {
try {
@@ -24,10 +24,13 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;
import javax.xml.namespace.QName;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import org.opensaml.saml.common.assertion.AssertionValidationException;
import org.opensaml.saml.common.assertion.ValidationContext;
import org.opensaml.saml.common.assertion.ValidationResult;
@@ -43,8 +46,11 @@ import org.opensaml.saml.saml2.assertion.impl.ProxyRestrictionConditionValidator
import org.opensaml.saml.saml2.core.Assertion;
import org.opensaml.saml.saml2.core.Condition;
import org.opensaml.saml.saml2.core.EncryptedAssertion;
import org.opensaml.saml.saml2.core.Issuer;
import org.opensaml.saml.saml2.core.NameID;
import org.opensaml.saml.saml2.core.OneTimeUse;
import org.opensaml.saml.saml2.core.Response;
import org.opensaml.saml.saml2.core.Subject;
import org.opensaml.saml.saml2.core.SubjectConfirmation;
import org.opensaml.saml.saml2.core.SubjectConfirmationData;
import org.opensaml.saml.saml2.encryption.Decrypter;
@@ -52,8 +58,6 @@ import org.opensaml.xmlsec.signature.support.SignaturePrevalidator;
import org.opensaml.xmlsec.signature.support.SignatureTrustEngine;
import org.springframework.core.convert.converter.Converter;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.Authentication;
@@ -111,6 +115,7 @@ import org.springframework.util.StringUtils;
* StatusResponse</a>
* @see <a href="https://shibboleth.atlassian.net/wiki/spaces/OSAML/overview">OpenSAML</a>
*/
@NullMarked
public final class OpenSaml5AuthenticationProvider implements AuthenticationProvider {
private static final String AUTHORITY = FactorGrantedAuthority.SAML_RESPONSE_AUTHORITY;
@@ -367,11 +372,12 @@ public final class OpenSaml5AuthenticationProvider implements AuthenticationProv
}
catch (Exception ex) {
String message = String.format("Invalid assertion [%s] for SAML response [%s]: %s", assertion.getID(),
((Response) assertion.getParent()).getID(), ex.getMessage());
((Response) Objects.requireNonNull(assertion.getParent())).getID(), ex.getMessage());
return Saml2ResponseValidatorResult.failure(new Saml2Error(Saml2ErrorCodes.INVALID_ASSERTION, message));
}
String message = String.format("Invalid assertion [%s] for SAML response [%s]: %s", assertion.getID(),
((Response) assertion.getParent()).getID(), context.getValidationFailureMessages());
((Response) Objects.requireNonNull(assertion.getParent())).getID(),
context.getValidationFailureMessages());
return Saml2ResponseValidatorResult.failure(new Saml2Error(Saml2ErrorCodes.INVALID_ASSERTION, message));
};
}
@@ -491,7 +497,6 @@ public final class OpenSaml5AuthenticationProvider implements AuthenticationProv
public static final class InResponseToValidator implements Converter<ResponseToken, Saml2ResponseValidatorResult> {
@Override
@NonNull
public Saml2ResponseValidatorResult convert(ResponseToken responseToken) {
AbstractSaml2AuthenticationRequest request = responseToken.getToken().getAuthenticationRequest();
Response response = responseToken.getResponse();
@@ -510,7 +515,6 @@ public final class OpenSaml5AuthenticationProvider implements AuthenticationProv
public static final class DestinationValidator implements Converter<ResponseToken, Saml2ResponseValidatorResult> {
@Override
@NonNull
public Saml2ResponseValidatorResult convert(ResponseToken responseToken) {
Response response = responseToken.getResponse();
Saml2AuthenticationToken token = responseToken.getToken();
@@ -536,15 +540,15 @@ public final class OpenSaml5AuthenticationProvider implements AuthenticationProv
public static final class IssuerValidator implements Converter<ResponseToken, Saml2ResponseValidatorResult> {
@Override
@NonNull
public Saml2ResponseValidatorResult convert(ResponseToken responseToken) {
Response response = responseToken.getResponse();
Saml2AuthenticationToken token = responseToken.getToken();
String issuer = response.getIssuer().getValue();
Issuer issuer = response.getIssuer();
Assert.notNull(issuer, "Response#Issuer cannot be null");
String assertingPartyEntityId = token.getRelyingPartyRegistration()
.getAssertingPartyMetadata()
.getEntityId();
if (!StringUtils.hasText(issuer) || !issuer.equals(assertingPartyEntityId)) {
if (!StringUtils.hasText(issuer.getValue()) || !assertingPartyEntityId.equals(issuer.getValue())) {
String message = String.format("Invalid issuer [%s] for SAML response [%s]", issuer, response.getID());
return Saml2ResponseValidatorResult.failure(new Saml2Error(Saml2ErrorCodes.INVALID_ISSUER, message));
}
@@ -642,11 +646,12 @@ public final class OpenSaml5AuthenticationProvider implements AuthenticationProv
}
catch (Exception ex) {
String message = String.format("Invalid assertion [%s] for SAML response [%s]: %s", assertion.getID(),
((Response) assertion.getParent()).getID(), ex.getMessage());
((Response) Objects.requireNonNull(assertion.getParent())).getID(), ex.getMessage());
return Saml2ResponseValidatorResult.failure(new Saml2Error(Saml2ErrorCodes.INVALID_ASSERTION, message));
}
String message = String.format("Invalid assertion [%s] for SAML response [%s]: %s", assertion.getID(),
((Response) assertion.getParent()).getID(), validationContext.getValidationFailureMessages());
((Response) Objects.requireNonNull(assertion.getParent())).getID(),
validationContext.getValidationFailureMessages());
return Saml2ResponseValidatorResult.failure(new Saml2Error(Saml2ErrorCodes.INVALID_ASSERTION, message));
}
@@ -704,7 +709,7 @@ public final class OpenSaml5AuthenticationProvider implements AuthenticationProv
return false;
}
private static String getAuthnRequestId(AbstractSaml2AuthenticationRequest serialized) {
private static @Nullable String getAuthnRequestId(@Nullable AbstractSaml2AuthenticationRequest serialized) {
return (serialized != null) ? serialized.getId() : null;
}
@@ -835,16 +840,13 @@ public final class OpenSaml5AuthenticationProvider implements AuthenticationProv
this.name = name;
}
@NonNull
@Override
public QName getServicedCondition() {
return this.name;
}
@NonNull
@Override
public ValidationResult validate(@NonNull Condition condition, @NonNull Assertion assertion,
@NonNull ValidationContext context) {
public ValidationResult validate(Condition condition, Assertion assertion, ValidationContext context) {
return ValidationResult.VALID;
}
@@ -855,16 +857,15 @@ public final class OpenSaml5AuthenticationProvider implements AuthenticationProv
private ValidSignatureAssertionValidator(@Nullable Collection<ConditionValidator> newConditionValidators,
@Nullable Collection<SubjectConfirmationValidator> newConfirmationValidators,
@Nullable Collection<StatementValidator> newStatementValidators,
@Nullable org.opensaml.saml.saml2.assertion.AssertionValidator newAssertionValidator,
org.opensaml.saml.saml2.assertion.@Nullable AssertionValidator newAssertionValidator,
@Nullable SignatureTrustEngine newTrustEngine,
@Nullable SignaturePrevalidator newSignaturePrevalidator) {
super(newConditionValidators, newConfirmationValidators, newStatementValidators, newAssertionValidator,
newTrustEngine, newSignaturePrevalidator);
}
@NonNull
@Override
protected ValidationResult validateSignature(@NonNull Assertion token, @NonNull ValidationContext context)
protected ValidationResult validateSignature(Assertion token, ValidationContext context)
throws AssertionValidationException {
return ValidationResult.VALID;
}
@@ -895,6 +896,7 @@ public final class OpenSaml5AuthenticationProvider implements AuthenticationProv
Response response = responseToken.response;
Saml2AuthenticationToken token = responseToken.token;
Assertion assertion = CollectionUtils.firstElement(response.getAssertions());
Assert.notNull(assertion, "samlResponse must have at least one assertion");
String username = this.principalNameConverter.convert(assertion);
String registrationId = responseToken.token.getRelyingPartyRegistration().getRegistrationId();
Saml2ResponseAssertionAccessor accessor = Saml2ResponseAssertion.withResponseValue(token.getSaml2Response())
@@ -944,7 +946,11 @@ public final class OpenSaml5AuthenticationProvider implements AuthenticationProv
throw new Saml2AuthenticationException(
Saml2Error.subjectNotFound("Assertion [" + assertion.getID() + "] is missing a subject"));
}
return assertion.getSubject().getNameID().getValue();
Subject subject = assertion.getSubject();
Assert.notNull(subject, "Assertion#Subject cannot be null");
NameID nameId = subject.getNameID();
Assert.notNull(nameId, "Assertion#Subject#NameID cannot be null");
return Objects.requireNonNull(nameId.getValue());
}
private static Collection<GrantedAuthority> grantedAuthorities(Assertion assertion) {
@@ -34,9 +34,12 @@ import java.util.Set;
import javax.xml.namespace.QName;
import net.shibboleth.shared.resolver.CriteriaSet;
import net.shibboleth.shared.xml.ParserPool;
import net.shibboleth.shared.xml.SerializeSupport;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import org.opensaml.core.criterion.EntityIdCriterion;
import org.opensaml.core.xml.XMLObject;
import org.opensaml.core.xml.XMLObjectBuilder;
@@ -117,6 +120,7 @@ import org.springframework.web.util.UriUtils;
/**
* For internal use only. Subject to breaking changes at any time.
*/
@NullMarked
final class OpenSaml5Template implements OpenSamlOperations {
private static final Log logger = LogFactory.getLog(OpenSaml5Template.class);
@@ -138,7 +142,9 @@ final class OpenSaml5Template implements OpenSamlOperations {
@Override
public <T extends XMLObject> T deserialize(InputStream serialized) {
try {
Document document = XMLObjectProviderRegistrySupport.getParserPool().parse(serialized);
ParserPool pool = XMLObjectProviderRegistrySupport.getParserPool();
Assert.notNull(pool, "ParserPool must be configured");
Document document = pool.parse(serialized);
Element element = document.getDocumentElement();
UnmarshallerFactory factory = XMLObjectProviderRegistrySupport.getUnmarshallerFactory();
Unmarshaller unmarshaller = factory.getUnmarshaller(element);
@@ -158,6 +164,7 @@ final class OpenSaml5Template implements OpenSamlOperations {
@Override
public OpenSaml5SerializationConfigurer serialize(XMLObject object) {
Marshaller marshaller = XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(object);
Assert.notNull(marshaller, "Marshaller for " + object.getElementQName() + " must be configured");
try {
return serialize(marshaller.marshall(object));
}
@@ -252,7 +259,9 @@ final class OpenSaml5Template implements OpenSamlOperations {
SignatureSigningParameters parameters = resolveSigningParameters();
this.components.putAll(params);
Credential credential = parameters.getSigningCredential();
Assert.notNull(credential, "credential cannot be null when signing a SAML payload");
String algorithmUri = parameters.getSignatureAlgorithm();
Assert.notNull(algorithmUri, "algorithmUri cannot be null when signing a SAML payload");
this.components.put(Saml2ParameterNames.SIG_ALG, algorithmUri);
UriComponentsBuilder builder = UriComponentsBuilder.newInstance();
for (Map.Entry<String, String> component : this.components.entrySet()) {
@@ -328,14 +337,14 @@ final class OpenSaml5Template implements OpenSamlOperations {
private final Collection<Saml2X509Credential> credentials;
private String entityId;
private @Nullable String entityId;
OpenSaml5VerificationConfigurer(Collection<Saml2X509Credential> credentials) {
this.credentials = credentials;
}
@Override
public VerificationConfigurer entityId(String entityId) {
public VerificationConfigurer entityId(@Nullable String entityId) {
this.entityId = entityId;
return this;
}
@@ -354,6 +363,7 @@ final class OpenSaml5Template implements OpenSamlOperations {
}
private CriteriaSet verificationCriteria(Issuer issuer) {
Assert.notNull(issuer.getValue(), "required elements must have a value");
return new CriteriaSet(new EvaluableEntityIDCredentialCriterion(new EntityIdCriterion(issuer.getValue())),
new EvaluableProtocolRoleDescriptorCriterion(new ProtocolCriterion(SAMLConstants.SAML20P_NS)),
new EvaluableUsageCredentialCriterion(new UsageCriterion(UsageType.SIGNING)));
@@ -362,12 +372,21 @@ final class OpenSaml5Template implements OpenSamlOperations {
@Override
public Collection<Saml2Error> verify(SignableXMLObject signable) {
if (signable instanceof StatusResponseType response) {
Assert.notNull(response.getID(), "Response#ID cannot be null");
Assert.notNull(response.getIssuer(), "Response#Issuer cannot be null");
Assert.notNull(response.getSignature(), "Response#Signature cannot be null");
return verifySignature(response.getID(), response.getIssuer(), response.getSignature());
}
if (signable instanceof RequestAbstractType request) {
Assert.notNull(request.getID(), "Request#ID cannot be null");
Assert.notNull(request.getIssuer(), "Request#Issuer cannot be null");
Assert.notNull(request.getSignature(), "Request#Signature cannot be null");
return verifySignature(request.getID(), request.getIssuer(), request.getSignature());
}
if (signable instanceof Assertion assertion) {
Assert.notNull(assertion.getID(), "Assertion#ID cannot be null");
Assert.notNull(assertion.getIssuer(), "Assertion#Issuer cannot be null");
Assert.notNull(assertion.getSignature(), "Assertion#Signature cannot be null");
return verifySignature(assertion.getID(), assertion.getIssuer(), assertion.getSignature());
}
throw new Saml2Exception("Unsupported object of type: " + signable.getClass().getName());
@@ -408,15 +427,15 @@ final class OpenSaml5Template implements OpenSamlOperations {
return Collections.singletonList(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE,
"Missing signature algorithm for object [" + parameters.getId() + "]"));
}
if (!parameters.hasSignature()) {
byte[] signature = parameters.getSignature();
if (signature == null) {
return Collections.singletonList(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE,
"Missing signature for object [" + parameters.getId() + "]"));
}
Collection<Saml2Error> errors = new ArrayList<>();
String algorithmUri = parameters.getAlgorithm();
try {
if (!trustEngine.validate(parameters.getSignature(), parameters.getContent(), algorithmUri, criteria,
null)) {
if (!trustEngine.validate(signature, parameters.getContent(), algorithmUri, criteria, null)) {
errors.add(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE,
"Invalid signature for object [" + parameters.getId() + "]"));
}
@@ -558,7 +577,7 @@ final class OpenSaml5Template implements OpenSamlOperations {
statement.getAttributes().addAll(decrypteds);
}
private void decryptSubject(Subject subject) {
private void decryptSubject(@Nullable Subject subject) {
if (subject != null) {
if (subject.getEncryptedID() != null) {
try {
@@ -16,12 +16,15 @@
package org.springframework.security.saml2.provider.service.authentication.logout;
import org.jspecify.annotations.NullMarked;
/**
* An OpenSAML 5.x compatible implementation of {@link Saml2LogoutResponseValidator}
*
* @author Josh Cummings
* @since 5.6
*/
@NullMarked
public final class OpenSaml5LogoutRequestValidator implements Saml2LogoutRequestValidator {
@SuppressWarnings("deprecation")
@@ -16,12 +16,15 @@
package org.springframework.security.saml2.provider.service.authentication.logout;
import org.jspecify.annotations.NullMarked;
/**
* An OpenSAML 5.x compatible implementation of {@link Saml2LogoutResponseValidator}
*
* @author Josh Cummings
* @since 5.6
*/
@NullMarked
public final class OpenSaml5LogoutResponseValidator implements Saml2LogoutResponseValidator {
@SuppressWarnings("deprecation")
@@ -34,9 +34,12 @@ import java.util.Set;
import javax.xml.namespace.QName;
import net.shibboleth.shared.resolver.CriteriaSet;
import net.shibboleth.shared.xml.ParserPool;
import net.shibboleth.shared.xml.SerializeSupport;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import org.opensaml.core.criterion.EntityIdCriterion;
import org.opensaml.core.xml.XMLObject;
import org.opensaml.core.xml.XMLObjectBuilder;
@@ -117,6 +120,7 @@ import org.springframework.web.util.UriUtils;
/**
* For internal use only. Subject to breaking changes at any time.
*/
@NullMarked
final class OpenSaml5Template implements OpenSamlOperations {
private static final Log logger = LogFactory.getLog(OpenSaml5Template.class);
@@ -138,7 +142,9 @@ final class OpenSaml5Template implements OpenSamlOperations {
@Override
public <T extends XMLObject> T deserialize(InputStream serialized) {
try {
Document document = XMLObjectProviderRegistrySupport.getParserPool().parse(serialized);
ParserPool pool = XMLObjectProviderRegistrySupport.getParserPool();
Assert.notNull(pool, "ParserPool must be configured");
Document document = pool.parse(serialized);
Element element = document.getDocumentElement();
UnmarshallerFactory factory = XMLObjectProviderRegistrySupport.getUnmarshallerFactory();
Unmarshaller unmarshaller = factory.getUnmarshaller(element);
@@ -158,6 +164,7 @@ final class OpenSaml5Template implements OpenSamlOperations {
@Override
public OpenSaml5SerializationConfigurer serialize(XMLObject object) {
Marshaller marshaller = XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(object);
Assert.notNull(marshaller, "Marshaller for " + object.getElementQName() + " must be configured");
try {
return serialize(marshaller.marshall(object));
}
@@ -252,7 +259,9 @@ final class OpenSaml5Template implements OpenSamlOperations {
SignatureSigningParameters parameters = resolveSigningParameters();
this.components.putAll(params);
Credential credential = parameters.getSigningCredential();
Assert.notNull(credential, "credential cannot be null when signing a SAML payload");
String algorithmUri = parameters.getSignatureAlgorithm();
Assert.notNull(algorithmUri, "algorithmUri cannot be null when signing a SAML payload");
this.components.put(Saml2ParameterNames.SIG_ALG, algorithmUri);
UriComponentsBuilder builder = UriComponentsBuilder.newInstance();
for (Map.Entry<String, String> component : this.components.entrySet()) {
@@ -328,14 +337,14 @@ final class OpenSaml5Template implements OpenSamlOperations {
private final Collection<Saml2X509Credential> credentials;
private String entityId;
private @Nullable String entityId;
OpenSaml5VerificationConfigurer(Collection<Saml2X509Credential> credentials) {
this.credentials = credentials;
}
@Override
public VerificationConfigurer entityId(String entityId) {
public VerificationConfigurer entityId(@Nullable String entityId) {
this.entityId = entityId;
return this;
}
@@ -354,6 +363,7 @@ final class OpenSaml5Template implements OpenSamlOperations {
}
private CriteriaSet verificationCriteria(Issuer issuer) {
Assert.notNull(issuer.getValue(), "required elements must have a value");
return new CriteriaSet(new EvaluableEntityIDCredentialCriterion(new EntityIdCriterion(issuer.getValue())),
new EvaluableProtocolRoleDescriptorCriterion(new ProtocolCriterion(SAMLConstants.SAML20P_NS)),
new EvaluableUsageCredentialCriterion(new UsageCriterion(UsageType.SIGNING)));
@@ -362,12 +372,21 @@ final class OpenSaml5Template implements OpenSamlOperations {
@Override
public Collection<Saml2Error> verify(SignableXMLObject signable) {
if (signable instanceof StatusResponseType response) {
Assert.notNull(response.getID(), "Response#ID cannot be null");
Assert.notNull(response.getIssuer(), "Response#Issuer cannot be null");
Assert.notNull(response.getSignature(), "Response#Signature cannot be null");
return verifySignature(response.getID(), response.getIssuer(), response.getSignature());
}
if (signable instanceof RequestAbstractType request) {
Assert.notNull(request.getID(), "Request#ID cannot be null");
Assert.notNull(request.getIssuer(), "Request#Issuer cannot be null");
Assert.notNull(request.getSignature(), "Request#Signature cannot be null");
return verifySignature(request.getID(), request.getIssuer(), request.getSignature());
}
if (signable instanceof Assertion assertion) {
Assert.notNull(assertion.getID(), "Assertion#ID cannot be null");
Assert.notNull(assertion.getIssuer(), "Assertion#Issuer cannot be null");
Assert.notNull(assertion.getSignature(), "Assertion#Signature cannot be null");
return verifySignature(assertion.getID(), assertion.getIssuer(), assertion.getSignature());
}
throw new Saml2Exception("Unsupported object of type: " + signable.getClass().getName());
@@ -408,15 +427,15 @@ final class OpenSaml5Template implements OpenSamlOperations {
return Collections.singletonList(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE,
"Missing signature algorithm for object [" + parameters.getId() + "]"));
}
if (!parameters.hasSignature()) {
byte[] signature = parameters.getSignature();
if (signature == null) {
return Collections.singletonList(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE,
"Missing signature for object [" + parameters.getId() + "]"));
}
Collection<Saml2Error> errors = new ArrayList<>();
String algorithmUri = parameters.getAlgorithm();
try {
if (!trustEngine.validate(parameters.getSignature(), parameters.getContent(), algorithmUri, criteria,
null)) {
if (!trustEngine.validate(signature, parameters.getContent(), algorithmUri, criteria, null)) {
errors.add(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE,
"Invalid signature for object [" + parameters.getId() + "]"));
}
@@ -558,7 +577,7 @@ final class OpenSaml5Template implements OpenSamlOperations {
statement.getAttributes().addAll(decrypteds);
}
private void decryptSubject(Subject subject) {
private void decryptSubject(@Nullable Subject subject) {
if (subject != null) {
if (subject.getEncryptedID() != null) {
try {
@@ -26,6 +26,8 @@ import java.util.zip.DeflaterOutputStream;
import java.util.zip.Inflater;
import java.util.zip.InflaterOutputStream;
import org.jspecify.annotations.NullMarked;
import org.springframework.security.saml2.Saml2Exception;
/**
@@ -35,6 +37,7 @@ import org.springframework.security.saml2.Saml2Exception;
*
* @author Josh Cummings
*/
@NullMarked
final class Saml2Utils {
private Saml2Utils() {
@@ -18,6 +18,7 @@ package org.springframework.security.saml2.provider.service.metadata;
import java.util.function.Consumer;
import org.jspecify.annotations.NullMarked;
import org.opensaml.saml.saml2.metadata.EntityDescriptor;
import org.springframework.security.saml2.core.OpenSamlInitializationService;
@@ -31,6 +32,7 @@ import org.springframework.security.saml2.provider.service.registration.RelyingP
* @author Josh Cummings
* @since 5.4
*/
@NullMarked
public final class OpenSaml5MetadataResolver implements Saml2MetadataResolver {
static {
@@ -34,9 +34,12 @@ import java.util.Set;
import javax.xml.namespace.QName;
import net.shibboleth.shared.resolver.CriteriaSet;
import net.shibboleth.shared.xml.ParserPool;
import net.shibboleth.shared.xml.SerializeSupport;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import org.opensaml.core.criterion.EntityIdCriterion;
import org.opensaml.core.xml.XMLObject;
import org.opensaml.core.xml.XMLObjectBuilder;
@@ -117,6 +120,7 @@ import org.springframework.web.util.UriUtils;
/**
* For internal use only. Subject to breaking changes at any time.
*/
@NullMarked
final class OpenSaml5Template implements OpenSamlOperations {
private static final Log logger = LogFactory.getLog(OpenSaml5Template.class);
@@ -138,7 +142,9 @@ final class OpenSaml5Template implements OpenSamlOperations {
@Override
public <T extends XMLObject> T deserialize(InputStream serialized) {
try {
Document document = XMLObjectProviderRegistrySupport.getParserPool().parse(serialized);
ParserPool pool = XMLObjectProviderRegistrySupport.getParserPool();
Assert.notNull(pool, "ParserPool must be configured");
Document document = pool.parse(serialized);
Element element = document.getDocumentElement();
UnmarshallerFactory factory = XMLObjectProviderRegistrySupport.getUnmarshallerFactory();
Unmarshaller unmarshaller = factory.getUnmarshaller(element);
@@ -158,6 +164,7 @@ final class OpenSaml5Template implements OpenSamlOperations {
@Override
public OpenSaml5SerializationConfigurer serialize(XMLObject object) {
Marshaller marshaller = XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(object);
Assert.notNull(marshaller, "Marshaller for " + object.getElementQName() + " must be configured");
try {
return serialize(marshaller.marshall(object));
}
@@ -252,7 +259,9 @@ final class OpenSaml5Template implements OpenSamlOperations {
SignatureSigningParameters parameters = resolveSigningParameters();
this.components.putAll(params);
Credential credential = parameters.getSigningCredential();
Assert.notNull(credential, "credential cannot be null when signing a SAML payload");
String algorithmUri = parameters.getSignatureAlgorithm();
Assert.notNull(algorithmUri, "algorithmUri cannot be null when signing a SAML payload");
this.components.put(Saml2ParameterNames.SIG_ALG, algorithmUri);
UriComponentsBuilder builder = UriComponentsBuilder.newInstance();
for (Map.Entry<String, String> component : this.components.entrySet()) {
@@ -328,14 +337,14 @@ final class OpenSaml5Template implements OpenSamlOperations {
private final Collection<Saml2X509Credential> credentials;
private String entityId;
private @Nullable String entityId;
OpenSaml5VerificationConfigurer(Collection<Saml2X509Credential> credentials) {
this.credentials = credentials;
}
@Override
public VerificationConfigurer entityId(String entityId) {
public VerificationConfigurer entityId(@Nullable String entityId) {
this.entityId = entityId;
return this;
}
@@ -354,6 +363,7 @@ final class OpenSaml5Template implements OpenSamlOperations {
}
private CriteriaSet verificationCriteria(Issuer issuer) {
Assert.notNull(issuer.getValue(), "required elements must have a value");
return new CriteriaSet(new EvaluableEntityIDCredentialCriterion(new EntityIdCriterion(issuer.getValue())),
new EvaluableProtocolRoleDescriptorCriterion(new ProtocolCriterion(SAMLConstants.SAML20P_NS)),
new EvaluableUsageCredentialCriterion(new UsageCriterion(UsageType.SIGNING)));
@@ -362,12 +372,21 @@ final class OpenSaml5Template implements OpenSamlOperations {
@Override
public Collection<Saml2Error> verify(SignableXMLObject signable) {
if (signable instanceof StatusResponseType response) {
Assert.notNull(response.getID(), "Response#ID cannot be null");
Assert.notNull(response.getIssuer(), "Response#Issuer cannot be null");
Assert.notNull(response.getSignature(), "Response#Signature cannot be null");
return verifySignature(response.getID(), response.getIssuer(), response.getSignature());
}
if (signable instanceof RequestAbstractType request) {
Assert.notNull(request.getID(), "Request#ID cannot be null");
Assert.notNull(request.getIssuer(), "Request#Issuer cannot be null");
Assert.notNull(request.getSignature(), "Request#Signature cannot be null");
return verifySignature(request.getID(), request.getIssuer(), request.getSignature());
}
if (signable instanceof Assertion assertion) {
Assert.notNull(assertion.getID(), "Assertion#ID cannot be null");
Assert.notNull(assertion.getIssuer(), "Assertion#Issuer cannot be null");
Assert.notNull(assertion.getSignature(), "Assertion#Signature cannot be null");
return verifySignature(assertion.getID(), assertion.getIssuer(), assertion.getSignature());
}
throw new Saml2Exception("Unsupported object of type: " + signable.getClass().getName());
@@ -408,15 +427,15 @@ final class OpenSaml5Template implements OpenSamlOperations {
return Collections.singletonList(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE,
"Missing signature algorithm for object [" + parameters.getId() + "]"));
}
if (!parameters.hasSignature()) {
byte[] signature = parameters.getSignature();
if (signature == null) {
return Collections.singletonList(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE,
"Missing signature for object [" + parameters.getId() + "]"));
}
Collection<Saml2Error> errors = new ArrayList<>();
String algorithmUri = parameters.getAlgorithm();
try {
if (!trustEngine.validate(parameters.getSignature(), parameters.getContent(), algorithmUri, criteria,
null)) {
if (!trustEngine.validate(signature, parameters.getContent(), algorithmUri, criteria, null)) {
errors.add(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE,
"Invalid signature for object [" + parameters.getId() + "]"));
}
@@ -558,7 +577,7 @@ final class OpenSaml5Template implements OpenSamlOperations {
statement.getAttributes().addAll(decrypteds);
}
private void decryptSubject(Subject subject) {
private void decryptSubject(@Nullable Subject subject) {
if (subject != null) {
if (subject.getEncryptedID() != null) {
try {
@@ -27,6 +27,9 @@ import java.util.Iterator;
import java.util.function.Consumer;
import net.shibboleth.shared.resolver.CriteriaSet;
import net.shibboleth.shared.xml.ParserPool;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import org.opensaml.core.criterion.EntityIdCriterion;
import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
import org.opensaml.saml.criterion.EntityRoleCriterion;
@@ -45,8 +48,6 @@ import org.opensaml.xmlsec.signature.support.impl.ExplicitKeySignatureTrustEngin
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.security.saml2.Saml2Exception;
import org.springframework.security.saml2.core.OpenSamlInitializationService;
import org.springframework.security.saml2.provider.service.registration.BaseOpenSamlAssertingPartyMetadataRepository.MetadataResolverAdapter;
@@ -65,6 +66,7 @@ import org.springframework.util.Assert;
* @see AssertingPartyMetadataRepository
* @see RelyingPartyRegistrations
*/
@NullMarked
public final class OpenSaml5AssertingPartyMetadataRepository implements AssertingPartyMetadataRepository {
static {
@@ -93,7 +95,6 @@ public final class OpenSaml5AssertingPartyMetadataRepository implements Assertin
* {@inheritDoc}
*/
@Override
@NonNull
public Iterator<AssertingPartyMetadata> iterator() {
return this.delegate.iterator();
}
@@ -101,9 +102,8 @@ public final class OpenSaml5AssertingPartyMetadataRepository implements Assertin
/**
* {@inheritDoc}
*/
@Nullable
@Override
public AssertingPartyMetadata findByEntityId(String entityId) {
public @Nullable AssertingPartyMetadata findByEntityId(String entityId) {
return this.delegate.findByEntityId(entityId);
}
@@ -222,7 +222,9 @@ public final class OpenSaml5AssertingPartyMetadataRepository implements Assertin
}
private MetadataResolver initialize(ResourceBackedMetadataResolver metadataResolver) {
metadataResolver.setParserPool(XMLObjectProviderRegistrySupport.getParserPool());
ParserPool pool = XMLObjectProviderRegistrySupport.getParserPool();
Assert.notNull(pool, "ParserPool must be configured");
metadataResolver.setParserPool(pool);
return BaseOpenSamlAssertingPartyMetadataRepository.initialize(metadataResolver);
}
@@ -264,7 +266,6 @@ public final class OpenSaml5AssertingPartyMetadataRepository implements Assertin
return this.resource.getFile();
}
@NonNull
@Override
public InputStream getInputStream() throws IOException {
return this.resource.getInputStream();
@@ -287,7 +288,7 @@ public final class OpenSaml5AssertingPartyMetadataRepository implements Assertin
}
@Override
public String getFilename() {
public @Nullable String getFilename() {
return this.resource.getFilename();
}
@@ -307,7 +308,7 @@ public final class OpenSaml5AssertingPartyMetadataRepository implements Assertin
}
@Override
EntityDescriptor resolveSingle(EntityIdCriterion entityId) throws Exception {
@Nullable EntityDescriptor resolveSingle(EntityIdCriterion entityId) throws Exception {
return super.metadataResolver.resolveSingle(new CriteriaSet(entityId));
}
@@ -34,9 +34,12 @@ import java.util.Set;
import javax.xml.namespace.QName;
import net.shibboleth.shared.resolver.CriteriaSet;
import net.shibboleth.shared.xml.ParserPool;
import net.shibboleth.shared.xml.SerializeSupport;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import org.opensaml.core.criterion.EntityIdCriterion;
import org.opensaml.core.xml.XMLObject;
import org.opensaml.core.xml.XMLObjectBuilder;
@@ -117,6 +120,7 @@ import org.springframework.web.util.UriUtils;
/**
* For internal use only. Subject to breaking changes at any time.
*/
@NullMarked
final class OpenSaml5Template implements OpenSamlOperations {
private static final Log logger = LogFactory.getLog(OpenSaml5Template.class);
@@ -138,7 +142,9 @@ final class OpenSaml5Template implements OpenSamlOperations {
@Override
public <T extends XMLObject> T deserialize(InputStream serialized) {
try {
Document document = XMLObjectProviderRegistrySupport.getParserPool().parse(serialized);
ParserPool pool = XMLObjectProviderRegistrySupport.getParserPool();
Assert.notNull(pool, "ParserPool must be configured");
Document document = pool.parse(serialized);
Element element = document.getDocumentElement();
UnmarshallerFactory factory = XMLObjectProviderRegistrySupport.getUnmarshallerFactory();
Unmarshaller unmarshaller = factory.getUnmarshaller(element);
@@ -158,6 +164,7 @@ final class OpenSaml5Template implements OpenSamlOperations {
@Override
public OpenSaml5SerializationConfigurer serialize(XMLObject object) {
Marshaller marshaller = XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(object);
Assert.notNull(marshaller, "Marshaller for " + object.getElementQName() + " must be configured");
try {
return serialize(marshaller.marshall(object));
}
@@ -252,7 +259,9 @@ final class OpenSaml5Template implements OpenSamlOperations {
SignatureSigningParameters parameters = resolveSigningParameters();
this.components.putAll(params);
Credential credential = parameters.getSigningCredential();
Assert.notNull(credential, "credential cannot be null when signing a SAML payload");
String algorithmUri = parameters.getSignatureAlgorithm();
Assert.notNull(algorithmUri, "algorithmUri cannot be null when signing a SAML payload");
this.components.put(Saml2ParameterNames.SIG_ALG, algorithmUri);
UriComponentsBuilder builder = UriComponentsBuilder.newInstance();
for (Map.Entry<String, String> component : this.components.entrySet()) {
@@ -328,14 +337,14 @@ final class OpenSaml5Template implements OpenSamlOperations {
private final Collection<Saml2X509Credential> credentials;
private String entityId;
private @Nullable String entityId;
OpenSaml5VerificationConfigurer(Collection<Saml2X509Credential> credentials) {
this.credentials = credentials;
}
@Override
public VerificationConfigurer entityId(String entityId) {
public VerificationConfigurer entityId(@Nullable String entityId) {
this.entityId = entityId;
return this;
}
@@ -354,6 +363,7 @@ final class OpenSaml5Template implements OpenSamlOperations {
}
private CriteriaSet verificationCriteria(Issuer issuer) {
Assert.notNull(issuer.getValue(), "required elements must have a value");
return new CriteriaSet(new EvaluableEntityIDCredentialCriterion(new EntityIdCriterion(issuer.getValue())),
new EvaluableProtocolRoleDescriptorCriterion(new ProtocolCriterion(SAMLConstants.SAML20P_NS)),
new EvaluableUsageCredentialCriterion(new UsageCriterion(UsageType.SIGNING)));
@@ -362,12 +372,21 @@ final class OpenSaml5Template implements OpenSamlOperations {
@Override
public Collection<Saml2Error> verify(SignableXMLObject signable) {
if (signable instanceof StatusResponseType response) {
Assert.notNull(response.getID(), "Response#ID cannot be null");
Assert.notNull(response.getIssuer(), "Response#Issuer cannot be null");
Assert.notNull(response.getSignature(), "Response#Signature cannot be null");
return verifySignature(response.getID(), response.getIssuer(), response.getSignature());
}
if (signable instanceof RequestAbstractType request) {
Assert.notNull(request.getID(), "Request#ID cannot be null");
Assert.notNull(request.getIssuer(), "Request#Issuer cannot be null");
Assert.notNull(request.getSignature(), "Request#Signature cannot be null");
return verifySignature(request.getID(), request.getIssuer(), request.getSignature());
}
if (signable instanceof Assertion assertion) {
Assert.notNull(assertion.getID(), "Assertion#ID cannot be null");
Assert.notNull(assertion.getIssuer(), "Assertion#Issuer cannot be null");
Assert.notNull(assertion.getSignature(), "Assertion#Signature cannot be null");
return verifySignature(assertion.getID(), assertion.getIssuer(), assertion.getSignature());
}
throw new Saml2Exception("Unsupported object of type: " + signable.getClass().getName());
@@ -408,15 +427,15 @@ final class OpenSaml5Template implements OpenSamlOperations {
return Collections.singletonList(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE,
"Missing signature algorithm for object [" + parameters.getId() + "]"));
}
if (!parameters.hasSignature()) {
byte[] signature = parameters.getSignature();
if (signature == null) {
return Collections.singletonList(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE,
"Missing signature for object [" + parameters.getId() + "]"));
}
Collection<Saml2Error> errors = new ArrayList<>();
String algorithmUri = parameters.getAlgorithm();
try {
if (!trustEngine.validate(parameters.getSignature(), parameters.getContent(), algorithmUri, criteria,
null)) {
if (!trustEngine.validate(signature, parameters.getContent(), algorithmUri, criteria, null)) {
errors.add(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE,
"Invalid signature for object [" + parameters.getId() + "]"));
}
@@ -558,7 +577,7 @@ final class OpenSaml5Template implements OpenSamlOperations {
statement.getAttributes().addAll(decrypteds);
}
private void decryptSubject(Subject subject) {
private void decryptSubject(@Nullable Subject subject) {
if (subject != null) {
if (subject.getEncryptedID() != null) {
try {
@@ -17,6 +17,8 @@
package org.springframework.security.saml2.provider.service.web;
import jakarta.servlet.http.HttpServletRequest;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import org.springframework.security.saml2.provider.service.authentication.AbstractSaml2AuthenticationRequest;
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationException;
@@ -35,6 +37,7 @@ import org.springframework.util.Assert;
* @author Josh Cummings
* @since 6.1
*/
@NullMarked
public final class OpenSaml5AuthenticationTokenConverter implements AuthenticationConverter {
private final BaseOpenSamlAuthenticationTokenConverter delegate;
@@ -76,7 +79,7 @@ public final class OpenSaml5AuthenticationTokenConverter implements Authenticati
* non-existent {@code registrationId}
*/
@Override
public Saml2AuthenticationToken convert(HttpServletRequest request) {
public @Nullable Saml2AuthenticationToken convert(HttpServletRequest request) {
return this.delegate.convert(request);
}
@@ -34,9 +34,12 @@ import java.util.Set;
import javax.xml.namespace.QName;
import net.shibboleth.shared.resolver.CriteriaSet;
import net.shibboleth.shared.xml.ParserPool;
import net.shibboleth.shared.xml.SerializeSupport;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import org.opensaml.core.criterion.EntityIdCriterion;
import org.opensaml.core.xml.XMLObject;
import org.opensaml.core.xml.XMLObjectBuilder;
@@ -117,6 +120,7 @@ import org.springframework.web.util.UriUtils;
/**
* For internal use only. Subject to breaking changes at any time.
*/
@NullMarked
final class OpenSaml5Template implements OpenSamlOperations {
private static final Log logger = LogFactory.getLog(OpenSaml5Template.class);
@@ -138,7 +142,9 @@ final class OpenSaml5Template implements OpenSamlOperations {
@Override
public <T extends XMLObject> T deserialize(InputStream serialized) {
try {
Document document = XMLObjectProviderRegistrySupport.getParserPool().parse(serialized);
ParserPool pool = XMLObjectProviderRegistrySupport.getParserPool();
Assert.notNull(pool, "ParserPool must be configured");
Document document = pool.parse(serialized);
Element element = document.getDocumentElement();
UnmarshallerFactory factory = XMLObjectProviderRegistrySupport.getUnmarshallerFactory();
Unmarshaller unmarshaller = factory.getUnmarshaller(element);
@@ -158,6 +164,7 @@ final class OpenSaml5Template implements OpenSamlOperations {
@Override
public OpenSaml5SerializationConfigurer serialize(XMLObject object) {
Marshaller marshaller = XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(object);
Assert.notNull(marshaller, "Marshaller for " + object.getElementQName() + " must be configured");
try {
return serialize(marshaller.marshall(object));
}
@@ -252,7 +259,9 @@ final class OpenSaml5Template implements OpenSamlOperations {
SignatureSigningParameters parameters = resolveSigningParameters();
this.components.putAll(params);
Credential credential = parameters.getSigningCredential();
Assert.notNull(credential, "credential cannot be null when signing a SAML payload");
String algorithmUri = parameters.getSignatureAlgorithm();
Assert.notNull(algorithmUri, "algorithmUri cannot be null when signing a SAML payload");
this.components.put(Saml2ParameterNames.SIG_ALG, algorithmUri);
UriComponentsBuilder builder = UriComponentsBuilder.newInstance();
for (Map.Entry<String, String> component : this.components.entrySet()) {
@@ -328,14 +337,14 @@ final class OpenSaml5Template implements OpenSamlOperations {
private final Collection<Saml2X509Credential> credentials;
private String entityId;
private @Nullable String entityId;
OpenSaml5VerificationConfigurer(Collection<Saml2X509Credential> credentials) {
this.credentials = credentials;
}
@Override
public VerificationConfigurer entityId(String entityId) {
public VerificationConfigurer entityId(@Nullable String entityId) {
this.entityId = entityId;
return this;
}
@@ -354,6 +363,7 @@ final class OpenSaml5Template implements OpenSamlOperations {
}
private CriteriaSet verificationCriteria(Issuer issuer) {
Assert.notNull(issuer.getValue(), "required elements must have a value");
return new CriteriaSet(new EvaluableEntityIDCredentialCriterion(new EntityIdCriterion(issuer.getValue())),
new EvaluableProtocolRoleDescriptorCriterion(new ProtocolCriterion(SAMLConstants.SAML20P_NS)),
new EvaluableUsageCredentialCriterion(new UsageCriterion(UsageType.SIGNING)));
@@ -362,12 +372,21 @@ final class OpenSaml5Template implements OpenSamlOperations {
@Override
public Collection<Saml2Error> verify(SignableXMLObject signable) {
if (signable instanceof StatusResponseType response) {
Assert.notNull(response.getID(), "Response#ID cannot be null");
Assert.notNull(response.getIssuer(), "Response#Issuer cannot be null");
Assert.notNull(response.getSignature(), "Response#Signature cannot be null");
return verifySignature(response.getID(), response.getIssuer(), response.getSignature());
}
if (signable instanceof RequestAbstractType request) {
Assert.notNull(request.getID(), "Request#ID cannot be null");
Assert.notNull(request.getIssuer(), "Request#Issuer cannot be null");
Assert.notNull(request.getSignature(), "Request#Signature cannot be null");
return verifySignature(request.getID(), request.getIssuer(), request.getSignature());
}
if (signable instanceof Assertion assertion) {
Assert.notNull(assertion.getID(), "Assertion#ID cannot be null");
Assert.notNull(assertion.getIssuer(), "Assertion#Issuer cannot be null");
Assert.notNull(assertion.getSignature(), "Assertion#Signature cannot be null");
return verifySignature(assertion.getID(), assertion.getIssuer(), assertion.getSignature());
}
throw new Saml2Exception("Unsupported object of type: " + signable.getClass().getName());
@@ -408,15 +427,15 @@ final class OpenSaml5Template implements OpenSamlOperations {
return Collections.singletonList(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE,
"Missing signature algorithm for object [" + parameters.getId() + "]"));
}
if (!parameters.hasSignature()) {
byte[] signature = parameters.getSignature();
if (signature == null) {
return Collections.singletonList(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE,
"Missing signature for object [" + parameters.getId() + "]"));
}
Collection<Saml2Error> errors = new ArrayList<>();
String algorithmUri = parameters.getAlgorithm();
try {
if (!trustEngine.validate(parameters.getSignature(), parameters.getContent(), algorithmUri, criteria,
null)) {
if (!trustEngine.validate(signature, parameters.getContent(), algorithmUri, criteria, null)) {
errors.add(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE,
"Invalid signature for object [" + parameters.getId() + "]"));
}
@@ -558,7 +577,7 @@ final class OpenSaml5Template implements OpenSamlOperations {
statement.getAttributes().addAll(decrypteds);
}
private void decryptSubject(Subject subject) {
private void decryptSubject(@Nullable Subject subject) {
if (subject != null) {
if (subject.getEncryptedID() != null) {
try {
@@ -21,6 +21,8 @@ import java.time.Instant;
import java.util.function.Consumer;
import jakarta.servlet.http.HttpServletRequest;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import org.opensaml.saml.saml2.core.AuthnRequest;
import org.springframework.core.convert.converter.Converter;
@@ -38,6 +40,7 @@ import org.springframework.util.Assert;
* @author Josh Cummings
* @since 5.7
*/
@NullMarked
public final class OpenSaml5AuthenticationRequestResolver implements Saml2AuthenticationRequestResolver {
private final BaseOpenSamlAuthenticationRequestResolver delegate;
@@ -65,7 +68,7 @@ public final class OpenSaml5AuthenticationRequestResolver implements Saml2Authen
}
@Override
public <T extends AbstractSaml2AuthenticationRequest> T resolve(HttpServletRequest request) {
public <T extends AbstractSaml2AuthenticationRequest> @Nullable T resolve(HttpServletRequest request) {
return this.delegate.resolve(request);
}
@@ -107,7 +110,7 @@ public final class OpenSaml5AuthenticationRequestResolver implements Saml2Authen
* @param relayStateResolver the {@link Converter} to use
* @since 5.8
*/
public void setRelayStateResolver(Converter<HttpServletRequest, String> relayStateResolver) {
public void setRelayStateResolver(Converter<HttpServletRequest, @Nullable String> relayStateResolver) {
Assert.notNull(relayStateResolver, "relayStateResolver cannot be null");
this.delegate.setRelayStateResolver(relayStateResolver);
}
@@ -34,9 +34,12 @@ import java.util.Set;
import javax.xml.namespace.QName;
import net.shibboleth.shared.resolver.CriteriaSet;
import net.shibboleth.shared.xml.ParserPool;
import net.shibboleth.shared.xml.SerializeSupport;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import org.opensaml.core.criterion.EntityIdCriterion;
import org.opensaml.core.xml.XMLObject;
import org.opensaml.core.xml.XMLObjectBuilder;
@@ -117,6 +120,7 @@ import org.springframework.web.util.UriUtils;
/**
* For internal use only. Subject to breaking changes at any time.
*/
@NullMarked
final class OpenSaml5Template implements OpenSamlOperations {
private static final Log logger = LogFactory.getLog(OpenSaml5Template.class);
@@ -138,7 +142,9 @@ final class OpenSaml5Template implements OpenSamlOperations {
@Override
public <T extends XMLObject> T deserialize(InputStream serialized) {
try {
Document document = XMLObjectProviderRegistrySupport.getParserPool().parse(serialized);
ParserPool pool = XMLObjectProviderRegistrySupport.getParserPool();
Assert.notNull(pool, "ParserPool must be configured");
Document document = pool.parse(serialized);
Element element = document.getDocumentElement();
UnmarshallerFactory factory = XMLObjectProviderRegistrySupport.getUnmarshallerFactory();
Unmarshaller unmarshaller = factory.getUnmarshaller(element);
@@ -158,6 +164,7 @@ final class OpenSaml5Template implements OpenSamlOperations {
@Override
public OpenSaml5SerializationConfigurer serialize(XMLObject object) {
Marshaller marshaller = XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(object);
Assert.notNull(marshaller, "Marshaller for " + object.getElementQName() + " must be configured");
try {
return serialize(marshaller.marshall(object));
}
@@ -252,7 +259,9 @@ final class OpenSaml5Template implements OpenSamlOperations {
SignatureSigningParameters parameters = resolveSigningParameters();
this.components.putAll(params);
Credential credential = parameters.getSigningCredential();
Assert.notNull(credential, "credential cannot be null when signing a SAML payload");
String algorithmUri = parameters.getSignatureAlgorithm();
Assert.notNull(algorithmUri, "algorithmUri cannot be null when signing a SAML payload");
this.components.put(Saml2ParameterNames.SIG_ALG, algorithmUri);
UriComponentsBuilder builder = UriComponentsBuilder.newInstance();
for (Map.Entry<String, String> component : this.components.entrySet()) {
@@ -328,14 +337,14 @@ final class OpenSaml5Template implements OpenSamlOperations {
private final Collection<Saml2X509Credential> credentials;
private String entityId;
private @Nullable String entityId;
OpenSaml5VerificationConfigurer(Collection<Saml2X509Credential> credentials) {
this.credentials = credentials;
}
@Override
public VerificationConfigurer entityId(String entityId) {
public VerificationConfigurer entityId(@Nullable String entityId) {
this.entityId = entityId;
return this;
}
@@ -354,6 +363,7 @@ final class OpenSaml5Template implements OpenSamlOperations {
}
private CriteriaSet verificationCriteria(Issuer issuer) {
Assert.notNull(issuer.getValue(), "required elements must have a value");
return new CriteriaSet(new EvaluableEntityIDCredentialCriterion(new EntityIdCriterion(issuer.getValue())),
new EvaluableProtocolRoleDescriptorCriterion(new ProtocolCriterion(SAMLConstants.SAML20P_NS)),
new EvaluableUsageCredentialCriterion(new UsageCriterion(UsageType.SIGNING)));
@@ -362,12 +372,21 @@ final class OpenSaml5Template implements OpenSamlOperations {
@Override
public Collection<Saml2Error> verify(SignableXMLObject signable) {
if (signable instanceof StatusResponseType response) {
Assert.notNull(response.getID(), "Response#ID cannot be null");
Assert.notNull(response.getIssuer(), "Response#Issuer cannot be null");
Assert.notNull(response.getSignature(), "Response#Signature cannot be null");
return verifySignature(response.getID(), response.getIssuer(), response.getSignature());
}
if (signable instanceof RequestAbstractType request) {
Assert.notNull(request.getID(), "Request#ID cannot be null");
Assert.notNull(request.getIssuer(), "Request#Issuer cannot be null");
Assert.notNull(request.getSignature(), "Request#Signature cannot be null");
return verifySignature(request.getID(), request.getIssuer(), request.getSignature());
}
if (signable instanceof Assertion assertion) {
Assert.notNull(assertion.getID(), "Assertion#ID cannot be null");
Assert.notNull(assertion.getIssuer(), "Assertion#Issuer cannot be null");
Assert.notNull(assertion.getSignature(), "Assertion#Signature cannot be null");
return verifySignature(assertion.getID(), assertion.getIssuer(), assertion.getSignature());
}
throw new Saml2Exception("Unsupported object of type: " + signable.getClass().getName());
@@ -408,15 +427,15 @@ final class OpenSaml5Template implements OpenSamlOperations {
return Collections.singletonList(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE,
"Missing signature algorithm for object [" + parameters.getId() + "]"));
}
if (!parameters.hasSignature()) {
byte[] signature = parameters.getSignature();
if (signature == null) {
return Collections.singletonList(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE,
"Missing signature for object [" + parameters.getId() + "]"));
}
Collection<Saml2Error> errors = new ArrayList<>();
String algorithmUri = parameters.getAlgorithm();
try {
if (!trustEngine.validate(parameters.getSignature(), parameters.getContent(), algorithmUri, criteria,
null)) {
if (!trustEngine.validate(signature, parameters.getContent(), algorithmUri, criteria, null)) {
errors.add(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE,
"Invalid signature for object [" + parameters.getId() + "]"));
}
@@ -558,7 +577,7 @@ final class OpenSaml5Template implements OpenSamlOperations {
statement.getAttributes().addAll(decrypteds);
}
private void decryptSubject(Subject subject) {
private void decryptSubject(@Nullable Subject subject) {
if (subject != null) {
if (subject.getEncryptedID() != null) {
try {
@@ -21,6 +21,8 @@ import java.time.Instant;
import java.util.function.Consumer;
import jakarta.servlet.http.HttpServletRequest;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import org.opensaml.saml.saml2.core.LogoutRequest;
import org.springframework.core.convert.converter.Converter;
@@ -39,6 +41,7 @@ import org.springframework.util.Assert;
* @author Gerhard Haege
* @since 5.6
*/
@NullMarked
public final class OpenSaml5LogoutRequestResolver implements Saml2LogoutRequestResolver {
private final BaseOpenSamlLogoutRequestResolver delegate;
@@ -64,7 +67,7 @@ public final class OpenSaml5LogoutRequestResolver implements Saml2LogoutRequestR
* {@inheritDoc}
*/
@Override
public Saml2LogoutRequest resolve(HttpServletRequest request, Authentication authentication) {
public @Nullable Saml2LogoutRequest resolve(HttpServletRequest request, Authentication authentication) {
return this.delegate.resolve(request, authentication);
}
@@ -17,6 +17,7 @@
package org.springframework.security.saml2.provider.service.web.authentication.logout;
import jakarta.servlet.http.HttpServletRequest;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import org.springframework.security.core.Authentication;
@@ -32,6 +33,7 @@ import org.springframework.util.Assert;
* An OpenSAML-based implementation of
* {@link Saml2LogoutRequestValidatorParametersResolver}
*/
@NullMarked
public final class OpenSaml5LogoutRequestValidatorParametersResolver
implements Saml2LogoutRequestValidatorParametersResolver {
@@ -21,6 +21,7 @@ import java.time.Instant;
import java.util.function.Consumer;
import jakarta.servlet.http.HttpServletRequest;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import org.opensaml.saml.saml2.core.LogoutRequest;
@@ -39,6 +40,7 @@ import org.springframework.util.Assert;
* @author Josh Cummings
* @since 5.6
*/
@NullMarked
public final class OpenSaml5LogoutResponseResolver implements Saml2LogoutResponseResolver {
private final BaseOpenSamlLogoutResponseResolver delegate;
@@ -64,7 +66,7 @@ public final class OpenSaml5LogoutResponseResolver implements Saml2LogoutRespons
* {@inheritDoc}
*/
@Override
public @Nullable Saml2LogoutResponse resolve(HttpServletRequest request, Authentication authentication) {
public @Nullable Saml2LogoutResponse resolve(HttpServletRequest request, @Nullable Authentication authentication) {
return this.delegate.resolve(request, authentication);
}
@@ -72,7 +74,7 @@ public final class OpenSaml5LogoutResponseResolver implements Saml2LogoutRespons
* {@inheritDoc}
*/
@Override
public @Nullable Saml2LogoutResponse resolve(HttpServletRequest request, Authentication authentication,
public @Nullable Saml2LogoutResponse resolve(HttpServletRequest request, @Nullable Authentication authentication,
Saml2AuthenticationException exception) {
return this.delegate.resolve(request, authentication, exception);
}
@@ -103,12 +105,12 @@ public final class OpenSaml5LogoutResponseResolver implements Saml2LogoutRespons
private final RelyingPartyRegistration registration;
private final Authentication authentication;
private final @Nullable Authentication authentication;
private final LogoutRequest logoutRequest;
public LogoutResponseParameters(HttpServletRequest request, RelyingPartyRegistration registration,
Authentication authentication, LogoutRequest logoutRequest) {
@Nullable Authentication authentication, LogoutRequest logoutRequest) {
this.request = request;
this.registration = registration;
this.authentication = authentication;
@@ -128,7 +130,7 @@ public final class OpenSaml5LogoutResponseResolver implements Saml2LogoutRespons
return this.registration;
}
public Authentication getAuthentication() {
public @Nullable Authentication getAuthentication() {
return this.authentication;
}
@@ -34,9 +34,12 @@ import java.util.Set;
import javax.xml.namespace.QName;
import net.shibboleth.shared.resolver.CriteriaSet;
import net.shibboleth.shared.xml.ParserPool;
import net.shibboleth.shared.xml.SerializeSupport;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import org.opensaml.core.criterion.EntityIdCriterion;
import org.opensaml.core.xml.XMLObject;
import org.opensaml.core.xml.XMLObjectBuilder;
@@ -117,6 +120,7 @@ import org.springframework.web.util.UriUtils;
/**
* For internal use only. Subject to breaking changes at any time.
*/
@NullMarked
final class OpenSaml5Template implements OpenSamlOperations {
private static final Log logger = LogFactory.getLog(OpenSaml5Template.class);
@@ -138,7 +142,9 @@ final class OpenSaml5Template implements OpenSamlOperations {
@Override
public <T extends XMLObject> T deserialize(InputStream serialized) {
try {
Document document = XMLObjectProviderRegistrySupport.getParserPool().parse(serialized);
ParserPool pool = XMLObjectProviderRegistrySupport.getParserPool();
Assert.notNull(pool, "ParserPool must be configured");
Document document = pool.parse(serialized);
Element element = document.getDocumentElement();
UnmarshallerFactory factory = XMLObjectProviderRegistrySupport.getUnmarshallerFactory();
Unmarshaller unmarshaller = factory.getUnmarshaller(element);
@@ -158,6 +164,7 @@ final class OpenSaml5Template implements OpenSamlOperations {
@Override
public OpenSaml5SerializationConfigurer serialize(XMLObject object) {
Marshaller marshaller = XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(object);
Assert.notNull(marshaller, "Marshaller for " + object.getElementQName() + " must be configured");
try {
return serialize(marshaller.marshall(object));
}
@@ -252,7 +259,9 @@ final class OpenSaml5Template implements OpenSamlOperations {
SignatureSigningParameters parameters = resolveSigningParameters();
this.components.putAll(params);
Credential credential = parameters.getSigningCredential();
Assert.notNull(credential, "credential cannot be null when signing a SAML payload");
String algorithmUri = parameters.getSignatureAlgorithm();
Assert.notNull(algorithmUri, "algorithmUri cannot be null when signing a SAML payload");
this.components.put(Saml2ParameterNames.SIG_ALG, algorithmUri);
UriComponentsBuilder builder = UriComponentsBuilder.newInstance();
for (Map.Entry<String, String> component : this.components.entrySet()) {
@@ -328,14 +337,14 @@ final class OpenSaml5Template implements OpenSamlOperations {
private final Collection<Saml2X509Credential> credentials;
private String entityId;
private @Nullable String entityId;
OpenSaml5VerificationConfigurer(Collection<Saml2X509Credential> credentials) {
this.credentials = credentials;
}
@Override
public VerificationConfigurer entityId(String entityId) {
public VerificationConfigurer entityId(@Nullable String entityId) {
this.entityId = entityId;
return this;
}
@@ -354,6 +363,7 @@ final class OpenSaml5Template implements OpenSamlOperations {
}
private CriteriaSet verificationCriteria(Issuer issuer) {
Assert.notNull(issuer.getValue(), "required elements must have a value");
return new CriteriaSet(new EvaluableEntityIDCredentialCriterion(new EntityIdCriterion(issuer.getValue())),
new EvaluableProtocolRoleDescriptorCriterion(new ProtocolCriterion(SAMLConstants.SAML20P_NS)),
new EvaluableUsageCredentialCriterion(new UsageCriterion(UsageType.SIGNING)));
@@ -362,12 +372,21 @@ final class OpenSaml5Template implements OpenSamlOperations {
@Override
public Collection<Saml2Error> verify(SignableXMLObject signable) {
if (signable instanceof StatusResponseType response) {
Assert.notNull(response.getID(), "Response#ID cannot be null");
Assert.notNull(response.getIssuer(), "Response#Issuer cannot be null");
Assert.notNull(response.getSignature(), "Response#Signature cannot be null");
return verifySignature(response.getID(), response.getIssuer(), response.getSignature());
}
if (signable instanceof RequestAbstractType request) {
Assert.notNull(request.getID(), "Request#ID cannot be null");
Assert.notNull(request.getIssuer(), "Request#Issuer cannot be null");
Assert.notNull(request.getSignature(), "Request#Signature cannot be null");
return verifySignature(request.getID(), request.getIssuer(), request.getSignature());
}
if (signable instanceof Assertion assertion) {
Assert.notNull(assertion.getID(), "Assertion#ID cannot be null");
Assert.notNull(assertion.getIssuer(), "Assertion#Issuer cannot be null");
Assert.notNull(assertion.getSignature(), "Assertion#Signature cannot be null");
return verifySignature(assertion.getID(), assertion.getIssuer(), assertion.getSignature());
}
throw new Saml2Exception("Unsupported object of type: " + signable.getClass().getName());
@@ -408,15 +427,15 @@ final class OpenSaml5Template implements OpenSamlOperations {
return Collections.singletonList(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE,
"Missing signature algorithm for object [" + parameters.getId() + "]"));
}
if (!parameters.hasSignature()) {
byte[] signature = parameters.getSignature();
if (signature == null) {
return Collections.singletonList(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE,
"Missing signature for object [" + parameters.getId() + "]"));
}
Collection<Saml2Error> errors = new ArrayList<>();
String algorithmUri = parameters.getAlgorithm();
try {
if (!trustEngine.validate(parameters.getSignature(), parameters.getContent(), algorithmUri, criteria,
null)) {
if (!trustEngine.validate(signature, parameters.getContent(), algorithmUri, criteria, null)) {
errors.add(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE,
"Invalid signature for object [" + parameters.getId() + "]"));
}
@@ -558,7 +577,7 @@ final class OpenSaml5Template implements OpenSamlOperations {
statement.getAttributes().addAll(decrypteds);
}
private void decryptSubject(Subject subject) {
private void decryptSubject(@Nullable Subject subject) {
if (subject != null) {
if (subject.getEncryptedID() != null) {
try {
@@ -22,6 +22,7 @@ import java.util.List;
import javax.xml.namespace.QName;
import net.shibboleth.shared.xml.ElementSupport;
import org.jspecify.annotations.Nullable;
import org.opensaml.core.xml.AbstractXMLObject;
import org.opensaml.core.xml.AbstractXMLObjectBuilder;
import org.opensaml.core.xml.ElementExtensibleXMLObject;
@@ -38,8 +39,6 @@ import org.opensaml.saml.common.xml.SAMLConstants;
import org.opensaml.saml.saml2.core.AttributeValue;
import org.w3c.dom.Element;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.security.saml2.core.OpenSamlInitializationService;
public final class TestCustomOpenSaml5Objects {
@@ -103,7 +102,6 @@ public final class TestCustomOpenSaml5Objects {
public static class CustomOpenSamlObjectImpl extends AbstractXMLObject implements CustomOpenSamlObject {
@NonNull
private IndexedXMLObjectChildrenList<XMLObject> unknownXMLObjects;
/**
@@ -113,28 +111,25 @@ public final class TestCustomOpenSaml5Objects {
* represents
* @param namespacePrefix the prefix for the given namespace
*/
protected CustomOpenSamlObjectImpl(@Nullable String namespaceURI, @NonNull String elementLocalName,
protected CustomOpenSamlObjectImpl(@Nullable String namespaceURI, String elementLocalName,
@Nullable String namespacePrefix) {
super(namespaceURI, elementLocalName, namespacePrefix);
super.getNamespaceManager().registerNamespaceDeclaration(new Namespace(CUSTOM_NS, TYPE_CUSTOM_PREFIX));
this.unknownXMLObjects = new IndexedXMLObjectChildrenList<>(this);
}
@NonNull
@Override
public List<XMLObject> getUnknownXMLObjects() {
return this.unknownXMLObjects;
}
@NonNull
@Override
public List<XMLObject> getUnknownXMLObjects(@NonNull QName typeOrName) {
public List<XMLObject> getUnknownXMLObjects(QName typeOrName) {
return (List<XMLObject>) this.unknownXMLObjects.subList(typeOrName);
}
@Nullable
@Override
public List<XMLObject> getOrderedChildren() {
public @Nullable List<XMLObject> getOrderedChildren() {
return Collections.unmodifiableList(this.unknownXMLObjects);
}
@@ -162,9 +157,8 @@ public final class TestCustomOpenSaml5Objects {
public static class CustomSamlObjectBuilder extends AbstractXMLObjectBuilder<CustomOpenSamlObject> {
@NonNull
@Override
public CustomOpenSamlObject buildObject(@Nullable String namespaceURI, @NonNull String localName,
public CustomOpenSamlObject buildObject(@Nullable String namespaceURI, String localName,
@Nullable String namespacePrefix) {
return new CustomOpenSamlObjectImpl(namespaceURI, localName, namespacePrefix);
}
@@ -178,7 +172,7 @@ public final class TestCustomOpenSaml5Objects {
}
@Override
protected void marshallElementContent(@NonNull XMLObject xmlObject, @NonNull Element domElement) {
protected void marshallElementContent(XMLObject xmlObject, Element domElement) {
final CustomOpenSamlObject customSamlObject = (CustomOpenSamlObject) xmlObject;
for (XMLObject object : customSamlObject.getOrderedChildren()) {
@@ -195,15 +189,14 @@ public final class TestCustomOpenSaml5Objects {
}
@Override
protected void processChildElement(@NonNull XMLObject parentXMLObject, @NonNull XMLObject childXMLObject)
protected void processChildElement(XMLObject parentXMLObject, XMLObject childXMLObject)
throws UnmarshallingException {
final CustomOpenSamlObject customSamlObject = (CustomOpenSamlObject) parentXMLObject;
customSamlObject.getUnknownXMLObjects().add(childXMLObject);
}
@NonNull
@Override
protected XMLObject buildXMLObject(@NonNull Element domElement) {
protected XMLObject buildXMLObject(Element domElement) {
return new CustomOpenSamlObjectImpl(SAMLConstants.SAML20_NS, AttributeValue.DEFAULT_ELEMENT_LOCAL_NAME,
CustomOpenSamlObject.TYPE_CUSTOM_PREFIX);
}