Explorar o código

Add missing KeyInfo

Closes gh-11354
Josh Cummings %!s(int64=3) %!d(string=hai) anos
pai
achega
89fb075e2d

+ 20 - 0
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/OpenSamlSigningUtils.java

@@ -42,6 +42,9 @@ import org.opensaml.xmlsec.SignatureSigningParametersResolver;
 import org.opensaml.xmlsec.criterion.SignatureSigningConfigurationCriterion;
 import org.opensaml.xmlsec.crypto.XMLSigningUtil;
 import org.opensaml.xmlsec.impl.BasicSignatureSigningConfiguration;
+import org.opensaml.xmlsec.keyinfo.KeyInfoGeneratorManager;
+import org.opensaml.xmlsec.keyinfo.NamedKeyInfoGeneratorManager;
+import org.opensaml.xmlsec.keyinfo.impl.X509KeyInfoGeneratorFactory;
 import org.opensaml.xmlsec.signature.SignableXMLObject;
 import org.opensaml.xmlsec.signature.support.SignatureConstants;
 import org.opensaml.xmlsec.signature.support.SignatureSupport;
@@ -102,6 +105,7 @@ final class OpenSamlSigningUtils {
 		signingConfiguration.setSignatureAlgorithms(algorithms);
 		signingConfiguration.setSignatureReferenceDigestMethods(digests);
 		signingConfiguration.setSignatureCanonicalizationAlgorithm(canonicalization);
+		signingConfiguration.setKeyInfoGeneratorManager(buildSignatureKeyInfoGeneratorManager());
 		criteria.add(new SignatureSigningConfigurationCriterion(signingConfiguration));
 		try {
 			SignatureSigningParameters parameters = resolver.resolveSingle(criteria);
@@ -113,6 +117,22 @@ final class OpenSamlSigningUtils {
 		}
 	}
 
+	private static NamedKeyInfoGeneratorManager buildSignatureKeyInfoGeneratorManager() {
+		final NamedKeyInfoGeneratorManager namedManager = new NamedKeyInfoGeneratorManager();
+
+		namedManager.setUseDefaultManager(true);
+		final KeyInfoGeneratorManager defaultManager = namedManager.getDefaultManager();
+
+		// Generator for X509Credentials
+		final X509KeyInfoGeneratorFactory x509Factory = new X509KeyInfoGeneratorFactory();
+		x509Factory.setEmitEntityCertificate(true);
+		x509Factory.setEmitEntityCertificateChain(true);
+
+		defaultManager.registerFactory(x509Factory);
+
+		return namedManager;
+	}
+
 	private static List<Credential> resolveSigningCredentials(RelyingPartyRegistration relyingPartyRegistration) {
 		List<Credential> credentials = new ArrayList<>();
 		for (Saml2X509Credential x509Credential : relyingPartyRegistration.getSigningX509Credentials()) {

+ 89 - 0
saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/OpenSamlSigningUtilsTests.java

@@ -0,0 +1,89 @@
+/*
+ * Copyright 2002-2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.security.saml2.provider.service.web.authentication;
+
+import java.util.UUID;
+
+import javax.xml.namespace.QName;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.saml.common.SAMLVersion;
+import org.opensaml.saml.saml2.core.Issuer;
+import org.opensaml.saml.saml2.core.Response;
+import org.opensaml.xmlsec.signature.Signature;
+
+import org.springframework.security.saml2.core.OpenSamlInitializationService;
+import org.springframework.security.saml2.core.TestSaml2X509Credentials;
+import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Test open SAML signatures
+ */
+public class OpenSamlSigningUtilsTests {
+
+	static {
+		OpenSamlInitializationService.initialize();
+	}
+
+	private RelyingPartyRegistration registration;
+
+	@BeforeEach
+	public void setup() {
+		this.registration = RelyingPartyRegistration.withRegistrationId("saml-idp")
+				.entityId("https://some.idp.example.com/entity-id").signingX509Credentials((c) -> {
+					c.add(TestSaml2X509Credentials.relyingPartySigningCredential());
+					c.add(TestSaml2X509Credentials.assertingPartySigningCredential());
+				}).assertingPartyDetails((c) -> c.entityId("https://some.idp.example.com/entity-id")
+						.singleSignOnServiceLocation("https://some.idp.example.com/service-location"))
+				.build();
+	}
+
+	@Test
+	public void whenSigningAnObjectThenKeyInfoIsPartOfTheSignature() {
+		Response response = response("destination", "issuer");
+		OpenSamlSigningUtils.sign(response, this.registration);
+		Signature signature = response.getSignature();
+		assertThat(signature).isNotNull();
+		assertThat(signature.getKeyInfo()).isNotNull();
+	}
+
+	Response response(String destination, String issuerEntityId) {
+		Response response = build(Response.DEFAULT_ELEMENT_NAME);
+		response.setID("R" + UUID.randomUUID());
+		response.setVersion(SAMLVersion.VERSION_20);
+		response.setID("_" + UUID.randomUUID());
+		response.setDestination(destination);
+		response.setIssuer(issuer(issuerEntityId));
+		return response;
+	}
+
+	Issuer issuer(String entityId) {
+		Issuer issuer = build(Issuer.DEFAULT_ELEMENT_NAME);
+		issuer.setValue(entityId);
+		return issuer;
+	}
+
+	<T extends XMLObject> T build(QName qName) {
+		return (T) XMLObjectProviderRegistrySupport.getBuilderFactory().getBuilder(qName).buildObject(qName);
+	}
+
+}