Răsfoiți Sursa

Remove OpenSamlImplementation

Closes gh-8775
Josh Cummings 5 ani în urmă
părinte
comite
08849e2652

+ 0 - 247
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlImplementation.java

@@ -1,247 +0,0 @@
-/*
- * Copyright 2002-2020 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.authentication;
-
-import java.io.ByteArrayInputStream;
-import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
-import java.util.Collection;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import javax.xml.namespace.QName;
-
-import net.shibboleth.utilities.java.support.xml.SerializeSupport;
-import net.shibboleth.utilities.java.support.xml.XMLParserException;
-import org.opensaml.core.xml.XMLObject;
-import org.opensaml.core.xml.XMLObjectBuilderFactory;
-import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
-import org.opensaml.core.xml.io.MarshallerFactory;
-import org.opensaml.core.xml.io.MarshallingException;
-import org.opensaml.core.xml.io.UnmarshallerFactory;
-import org.opensaml.core.xml.io.UnmarshallingException;
-import org.opensaml.saml.saml2.core.AuthnRequest;
-import org.opensaml.saml.saml2.encryption.EncryptedElementTypeEncryptedKeyResolver;
-import org.opensaml.security.SecurityException;
-import org.opensaml.security.credential.BasicCredential;
-import org.opensaml.security.credential.Credential;
-import org.opensaml.security.credential.CredentialSupport;
-import org.opensaml.security.credential.UsageType;
-import org.opensaml.security.x509.BasicX509Credential;
-import org.opensaml.xmlsec.SignatureSigningParameters;
-import org.opensaml.xmlsec.crypto.XMLSigningUtil;
-import org.opensaml.xmlsec.encryption.support.ChainingEncryptedKeyResolver;
-import org.opensaml.xmlsec.encryption.support.EncryptedKeyResolver;
-import org.opensaml.xmlsec.encryption.support.InlineEncryptedKeyResolver;
-import org.opensaml.xmlsec.encryption.support.SimpleRetrievalMethodEncryptedKeyResolver;
-import org.opensaml.xmlsec.signature.support.SignatureConstants;
-import org.opensaml.xmlsec.signature.support.SignatureException;
-import org.opensaml.xmlsec.signature.support.SignatureSupport;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
-import org.springframework.security.saml2.Saml2Exception;
-import org.springframework.security.saml2.core.OpenSamlInitializationService;
-import org.springframework.security.saml2.core.Saml2X509Credential;
-import org.springframework.util.Assert;
-import org.springframework.web.util.UriUtils;
-
-import static java.util.Arrays.asList;
-import static org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport.getParserPool;
-import static org.springframework.util.StringUtils.hasText;
-
-/**
- * @since 5.2
- */
-final class OpenSamlImplementation {
-	static {
-		OpenSamlInitializationService.initialize();
-	}
-
-	private static OpenSamlImplementation instance = new OpenSamlImplementation();
-	private static XMLObjectBuilderFactory xmlObjectBuilderFactory =
-			XMLObjectProviderRegistrySupport.getBuilderFactory();
-
-	private final EncryptedKeyResolver encryptedKeyResolver = new ChainingEncryptedKeyResolver(
-			asList(
-					new InlineEncryptedKeyResolver(),
-					new EncryptedElementTypeEncryptedKeyResolver(),
-					new SimpleRetrievalMethodEncryptedKeyResolver()
-			)
-	);
-
-	/*
-	 * ==============================================================
-	 * PUBLIC METHODS
-	 * ==============================================================
-	 */
-	static OpenSamlImplementation getInstance() {
-		return instance;
-	}
-
-	EncryptedKeyResolver getEncryptedKeyResolver() {
-		return this.encryptedKeyResolver;
-	}
-
-	<T> T buildSamlObject(QName qName) {
-		return (T) xmlObjectBuilderFactory.getBuilder(qName).buildObject(qName);
-	}
-
-	XMLObject resolve(String xml) {
-		return resolve(xml.getBytes(StandardCharsets.UTF_8));
-	}
-
-	String serialize(XMLObject xmlObject) {
-		final MarshallerFactory marshallerFactory = XMLObjectProviderRegistrySupport.getMarshallerFactory();
-		try {
-			Element element = marshallerFactory.getMarshaller(xmlObject).marshall(xmlObject);
-			return SerializeSupport.nodeToString(element);
-		} catch (MarshallingException e) {
-			throw new Saml2Exception(e);
-		}
-	}
-
-	/**
-	 * Returns query parameter after creating a Query String signature
-	 * All return values are unencoded and will need to be encoded prior to sending
-	 * The methods {@link UriUtils#encode(String, Charset)} and {@link UriUtils#decode(String, Charset)}
-	 * with the {@link StandardCharsets#ISO_8859_1} character set are used for all URL encoding/decoding.
-	 * @param signingCredentials - credentials to be used for signature
-	 * @return a map of unencoded query parameters with the following keys:
-	 * {@code {SAMLRequest, RelayState (may be null)}, SigAlg, Signature}
-	 *
-	 */
-	Map<String, String> signQueryParameters(
-			Collection<Saml2X509Credential> signingCredentials,
-			String samlRequest,
-			String relayState) {
-		Assert.notNull(samlRequest, "samlRequest cannot be null");
-		String algorithmUri = SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256;
-		StringBuilder queryString = new StringBuilder();
-		queryString
-				.append("SAMLRequest")
-				.append("=")
-				.append(UriUtils.encode(samlRequest, StandardCharsets.ISO_8859_1))
-				.append("&");
-		if (hasText(relayState)) {
-			queryString
-					.append("RelayState")
-					.append("=")
-					.append(UriUtils.encode(relayState, StandardCharsets.ISO_8859_1))
-					.append("&");
-		}
-		queryString
-				.append("SigAlg")
-				.append("=")
-				.append(UriUtils.encode(algorithmUri, StandardCharsets.ISO_8859_1));
-
-		try {
-			byte[] rawSignature = XMLSigningUtil.signWithURI(
-					getSigningCredential(signingCredentials, ""),
-					algorithmUri,
-					queryString.toString().getBytes(StandardCharsets.UTF_8)
-			);
-			String b64Signature = Saml2Utils.samlEncode(rawSignature);
-
-			Map<String, String> result = new LinkedHashMap<>();
-			result.put("SAMLRequest", samlRequest);
-			if (hasText(relayState)) {
-				result.put("RelayState", relayState);
-			}
-			result.put("SigAlg", algorithmUri);
-			result.put("Signature", b64Signature);
-			return result;
-		}
-		catch (SecurityException e) {
-			throw new Saml2Exception(e);
-		}
-	}
-
-	/*
-	 * ==============================================================
-	 * PRIVATE METHODS
-	 * ==============================================================
-	 */
-
-	private XMLObject resolve(byte[] xml) {
-		XMLObject parsed = parse(xml);
-		if (parsed != null) {
-			return parsed;
-		}
-		throw new Saml2Exception("Deserialization not supported for given data set");
-	}
-
-	private XMLObject parse(byte[] xml) {
-		try {
-			Document document = getParserPool().parse(new ByteArrayInputStream(xml));
-			Element element = document.getDocumentElement();
-			return getUnmarshallerFactory().getUnmarshaller(element).unmarshall(element);
-		}
-		catch (UnmarshallingException | XMLParserException e) {
-			throw new Saml2Exception(e);
-		}
-	}
-
-	private UnmarshallerFactory getUnmarshallerFactory() {
-		return XMLObjectProviderRegistrySupport.getUnmarshallerFactory();
-	}
-
-
-	private Saml2X509Credential hasSigningCredential(Collection<Saml2X509Credential> credentials) {
-		for (Saml2X509Credential c : credentials) {
-			if (c.isSigningCredential()) {
-				return c;
-			}
-		}
-		return null;
-	}
-
-	private Credential getSigningCredential(Collection<Saml2X509Credential> signingCredential,
-											String localSpEntityId
-	) {
-		Saml2X509Credential credential = hasSigningCredential(signingCredential);
-		if (credential == null) {
-			throw new Saml2Exception("no signing credential configured");
-		}
-		BasicCredential cred = getBasicCredential(credential);
-		cred.setEntityId(localSpEntityId);
-		cred.setUsageType(UsageType.SIGNING);
-		return cred;
-	}
-
-	private void signAuthnRequest(AuthnRequest authnRequest, Collection<Saml2X509Credential> signingCredentials) {
-		SignatureSigningParameters parameters = new SignatureSigningParameters();
-		Credential credential = getSigningCredential(signingCredentials, authnRequest.getIssuer().getValue());
-		parameters.setSigningCredential(credential);
-		parameters.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256);
-		parameters.setSignatureReferenceDigestMethod(SignatureConstants.ALGO_ID_DIGEST_SHA256);
-		parameters.setSignatureCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
-		try {
-			SignatureSupport.signObject(authnRequest, parameters);
-		} catch (MarshallingException | SignatureException | SecurityException e) {
-			throw new Saml2Exception(e);
-		}
-
-	}
-
-	private BasicX509Credential getBasicCredential(Saml2X509Credential credential) {
-		return CredentialSupport.getSimpleCredential(
-				credential.getCertificate(),
-				credential.getPrivateKey()
-		);
-	}
-
-}

+ 0 - 70
saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlImplementationTests.java

@@ -1,70 +0,0 @@
-/*
- * Copyright 2002-2020 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.authentication;
-
-import java.util.Arrays;
-import java.util.Map;
-
-import org.junit.Test;
-import org.opensaml.xmlsec.crypto.XMLSigningUtil;
-
-import org.springframework.security.saml2.core.Saml2X509Credential;
-import org.springframework.web.util.UriUtils;
-
-import static java.nio.charset.StandardCharsets.ISO_8859_1;
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.opensaml.xmlsec.signature.support.SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256;
-import static org.springframework.security.saml2.provider.service.authentication.TestOpenSamlObjects.getSigningCredential;
-import static org.springframework.security.saml2.core.TestSaml2X509Credentials.assertingPartySigningCredential;
-import static org.springframework.security.saml2.core.TestSaml2X509Credentials.relyingPartyVerifyingCredential;
-
-public class OpenSamlImplementationTests {
-
-	@Test
-	public void getInstance() {
-		OpenSamlImplementation.getInstance();
-	}
-
-	@Test
-	public void signQueryParametersWhenDataSuppliedReturnsValidSignature() throws Exception {
-		OpenSamlImplementation impl = OpenSamlImplementation.getInstance();
-		Saml2X509Credential signingCredential = assertingPartySigningCredential();
-		Saml2X509Credential verifyingCredential = relyingPartyVerifyingCredential();
-		String samlRequest = "saml-request-example";
-		String encoded = Saml2Utils.samlEncode(samlRequest.getBytes(UTF_8));
-		String relayState = "test relay state";
-		Map<String, String> parameters = impl.signQueryParameters(Arrays.asList(signingCredential), encoded, relayState);
-
-		String queryString = "SAMLRequest=" +
-				UriUtils.encode(encoded, ISO_8859_1) +
-				"&RelayState=" +
-				UriUtils.encode(relayState, ISO_8859_1) +
-				"&SigAlg=" +
-				UriUtils.encode(ALGO_ID_SIGNATURE_RSA_SHA256, ISO_8859_1);
-
-
-		byte[] signature = Saml2Utils.samlDecode(parameters.get("Signature"));
-		boolean result = XMLSigningUtil.verifyWithURI(
-				getSigningCredential(verifyingCredential, "local-sp-entity-id"),
-				ALGO_ID_SIGNATURE_RSA_SHA256,
-				signature,
-				queryString.getBytes(UTF_8)
-		);
-		assertThat(result).isTrue();
-	}
-}

+ 18 - 13
saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/TestOpenSamlObjects.java

@@ -17,18 +17,19 @@
 package org.springframework.security.saml2.provider.service.authentication;
 
 import java.security.cert.X509Certificate;
+import java.util.ArrayList;
 import java.util.Base64;
-import java.util.UUID;
 import java.util.List;
-import java.util.ArrayList;
+import java.util.UUID;
 import javax.crypto.SecretKey;
 import javax.crypto.spec.SecretKeySpec;
+import javax.xml.namespace.QName;
 
 import org.apache.xml.security.encryption.XMLCipherParameters;
 import org.joda.time.DateTime;
 import org.joda.time.Duration;
+import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.io.MarshallingException;
-
 import org.opensaml.core.xml.schema.XSAny;
 import org.opensaml.core.xml.schema.XSBoolean;
 import org.opensaml.core.xml.schema.XSBooleanValue;
@@ -77,13 +78,13 @@ import org.springframework.security.saml2.Saml2Exception;
 import org.springframework.security.saml2.core.OpenSamlInitializationService;
 import org.springframework.security.saml2.core.Saml2X509Credential;
 
+import static org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport.getBuilderFactory;
+
 final class TestOpenSamlObjects {
 	static {
 		OpenSamlInitializationService.initialize();
 	}
 
-	private static OpenSamlImplementation saml = OpenSamlImplementation.getInstance();
-
 	private static String USERNAME = "test@saml.user";
 	private static String DESTINATION = "https://localhost/login/saml2/sso/idp-alias";
 	private static String RELYING_PARTY_ENTITY_ID = "https://localhost/saml2/service-provider-metadata/idp-alias";
@@ -96,7 +97,7 @@ final class TestOpenSamlObjects {
 	}
 
 	static Response response(String destination, String issuerEntityId) {
-		Response response = saml.buildSamlObject(Response.DEFAULT_ELEMENT_NAME);
+		Response response = build(Response.DEFAULT_ELEMENT_NAME);
 		response.setID("R"+UUID.randomUUID().toString());
 		response.setIssueInstant(DateTime.now());
 		response.setVersion(SAMLVersion.VERSION_20);
@@ -116,7 +117,7 @@ final class TestOpenSamlObjects {
 			String recipientEntityId,
 			String recipientUri
 	) {
-		Assertion assertion = saml.buildSamlObject(Assertion.DEFAULT_ELEMENT_NAME);
+		Assertion assertion = build(Assertion.DEFAULT_ELEMENT_NAME);
 		assertion.setID("A"+ UUID.randomUUID().toString());
 		assertion.setIssueInstant(DateTime.now());
 		assertion.setVersion(SAMLVersion.VERSION_20);
@@ -136,13 +137,13 @@ final class TestOpenSamlObjects {
 
 
 	static Issuer issuer(String entityId) {
-		Issuer issuer = saml.buildSamlObject(Issuer.DEFAULT_ELEMENT_NAME);
+		Issuer issuer = build(Issuer.DEFAULT_ELEMENT_NAME);
 		issuer.setValue(entityId);
 		return issuer;
 	}
 
 	static Subject subject(String principalName) {
-		Subject subject = saml.buildSamlObject(Subject.DEFAULT_ELEMENT_NAME);
+		Subject subject = build(Subject.DEFAULT_ELEMENT_NAME);
 
 		if (principalName != null) {
 			subject.setNameID(nameId(principalName));
@@ -152,17 +153,17 @@ final class TestOpenSamlObjects {
 	}
 
 	static NameID nameId(String principalName) {
-		NameID nameId = saml.buildSamlObject(NameID.DEFAULT_ELEMENT_NAME);
+		NameID nameId = build(NameID.DEFAULT_ELEMENT_NAME);
 		nameId.setValue(principalName);
 		return nameId;
 	}
 
 	static SubjectConfirmation subjectConfirmation() {
-		return saml.buildSamlObject(SubjectConfirmation.DEFAULT_ELEMENT_NAME);
+		return build(SubjectConfirmation.DEFAULT_ELEMENT_NAME);
 	}
 
 	static SubjectConfirmationData subjectConfirmationData(String recipient) {
-		SubjectConfirmationData subject = saml.buildSamlObject(SubjectConfirmationData.DEFAULT_ELEMENT_NAME);
+		SubjectConfirmationData subject = build(SubjectConfirmationData.DEFAULT_ELEMENT_NAME);
 		subject.setRecipient(recipient);
 		subject.setNotBefore(DateTime.now().minus(Duration.millis(5 * 60 * 1000)));
 		subject.setNotOnOrAfter(DateTime.now().plus(Duration.millis(5 * 60 * 1000)));
@@ -170,7 +171,7 @@ final class TestOpenSamlObjects {
 	}
 
 	static Conditions conditions() {
-		Conditions conditions = saml.buildSamlObject(Conditions.DEFAULT_ELEMENT_NAME);
+		Conditions conditions = build(Conditions.DEFAULT_ELEMENT_NAME);
 		conditions.setNotBefore(DateTime.now().minus(Duration.millis(5 * 60 * 1000)));
 		conditions.setNotOnOrAfter(DateTime.now().plus(Duration.millis(5 * 60 * 1000)));
 		return conditions;
@@ -362,4 +363,8 @@ final class TestOpenSamlObjects {
 
 		return attributeStatements;
 	}
+
+	static <T extends XMLObject> T build(QName qName) {
+		return (T) getBuilderFactory().getBuilder(qName).buildObject(qName);
+	}
 }