Procházet zdrojové kódy

Revert "Correct signature handling for SAML2 AuthNRequest"

This reverts commit a3e09fadd77cb6bbacbd626c48deb2a4473e1e54.
Build failure on Java 9+

XML generation does not add linefeeds by default
Change since Java 8
Filip Hanik před 5 roky
rodič
revize
43098d41cc
21 změnil soubory, kde provedl 241 přidání a 1290 odebrání
  1. 0 148
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/AbstractSaml2AuthenticationRequest.java
  2. 12 62
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationRequestFactory.java
  3. 6 70
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlImplementation.java
  4. 3 17
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationRequest.java
  5. 0 172
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationRequestContext.java
  6. 9 86
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationRequestFactory.java
  7. 0 85
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2PostAuthenticationRequest.java
  8. 0 133
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2RedirectAuthenticationRequest.java
  9. 0 73
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2Utils.java
  10. 0 45
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/Saml2MessageBinding.java
  11. 0 88
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2ServletUtils.java
  12. 68 8
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2Utils.java
  13. 5 5
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2WebSsoAuthenticationFilter.java
  14. 30 35
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2WebSsoAuthenticationRequestFilter.java
  15. 11 59
      saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationRequestFactoryTests.java
  16. 0 55
      saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlImplementationTests.java
  17. 0 72
      saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationRequestFactoryTests.java
  18. 2 2
      saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2UtilsTests.java
  19. 29 50
      saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2WebSsoAuthenticationRequestFilterTests.java
  20. 52 6
      samples/boot/saml2login/src/integration-test/java/org/springframework/security/samples/OpenSamlActionTestingSupport.java
  21. 14 19
      samples/boot/saml2login/src/integration-test/java/org/springframework/security/samples/Saml2LoginIntegrationTests.java

+ 0 - 148
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/AbstractSaml2AuthenticationRequest.java

@@ -1,148 +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 org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
-import org.springframework.util.Assert;
-
-import java.nio.charset.Charset;
-
-/**
- * Data holder for {@code AuthNRequest} parameters to be sent using either the
- * {@link Saml2MessageBinding#POST} or {@link Saml2MessageBinding#REDIRECT} binding.
- * Data will be encoded and possibly deflated, but will not be escaped for transport,
- * ie URL encoded, {@link org.springframework.web.util.UriUtils#encode(String, Charset)}
- * or HTML encoded, {@link org.springframework.web.util.HtmlUtils#htmlEscape(String)}.
- * https://www.oasis-open.org/committees/download.php/35711/sstc-saml-core-errata-2.0-wd-06-diff.pdf (line 2031)
- *
- * @see Saml2AuthenticationRequestFactory#createPostAuthenticationRequest(Saml2AuthenticationRequestContext)
- * @see Saml2AuthenticationRequestFactory#createRedirectAuthenticationRequest(Saml2AuthenticationRequestContext)
- * @since 5.3
- */
-abstract class AbstractSaml2AuthenticationRequest {
-
-	private final String samlRequest;
-	private final String relayState;
-	private final String authenticationRequestUri;
-
-	/**
-	 * Mandatory constructor for the {@link AbstractSaml2AuthenticationRequest}
-	 * @param samlRequest - the SAMLRequest XML data, SAML encoded, cannot be empty or null
-	 * @param relayState - RelayState value that accompanies the request, may be null
-	 * @param authenticationRequestUri - The authenticationRequestUri, a URL, where to send the XML message, cannot be empty or null
-	 */
-	AbstractSaml2AuthenticationRequest(
-			String samlRequest,
-			String relayState,
-			String authenticationRequestUri) {
-		Assert.hasText(samlRequest, "samlRequest cannot be null or empty");
-		Assert.hasText(authenticationRequestUri, "authenticationRequestUri cannot be null or empty");
-		this.authenticationRequestUri = authenticationRequestUri;
-		this.samlRequest = samlRequest;
-		this.relayState = relayState;
-	}
-
-	/**
-	 * Returns the AuthNRequest XML value to be sent. This value is already encoded for transport.
-	 * If {@link #getBinding()} is {@link Saml2MessageBinding#REDIRECT} the value is deflated and SAML encoded.
-	 * If {@link #getBinding()} is {@link Saml2MessageBinding#POST} the value is SAML encoded.
-	 * @return the SAMLRequest parameter value
-	 */
-	public String getSamlRequest() {
-		return this.samlRequest;
-	}
-
-	/**
-	 * Returns the RelayState value, if present in the parameters
-	 * @return the RelayState value, or null if not available
-	 */
-	public String getRelayState() {
-		return this.relayState;
-	}
-
-	/**
-	 * Returns the URI endpoint that this AuthNRequest should be sent to.
-	 * @return the URI endpoint for this message
-	 */
-	public String getAuthenticationRequestUri() {
-		return this.authenticationRequestUri;
-	}
-
-	/**
-	 * Returns the binding this AuthNRequest will be sent and
-	 * encoded with. If {@link Saml2MessageBinding#REDIRECT} is used, the DEFLATE encoding will be automatically applied.
-	 * @return the binding this message will be sent with.
-	 */
-	public abstract Saml2MessageBinding getBinding();
-
-	/**
-	 * A builder for {@link AbstractSaml2AuthenticationRequest} and its subclasses.
-	 */
-	static class Builder<T extends Builder<T>> {
-		String authenticationRequestUri;
-		String samlRequest;
-		String relayState;
-
-		protected Builder() {
-		}
-
-		/**
-		 * Casting the return as the generic subtype, when returning itself
-		 * @return this object
-		 */
-		@SuppressWarnings("unchecked")
-		protected final T _this() {
-			return (T) this;
-		}
-
-
-		/**
-		 * Sets the {@code RelayState} parameter that will accompany this AuthNRequest
-		 *
-		 * @param relayState the relay state value, unencoded. if null or empty, the parameter will be removed from the
-		 * map.
-		 * @return this object
-		 */
-		public T relayState(String relayState) {
-			this.relayState = relayState;
-			return _this();
-		}
-
-		/**
-		 * Sets the {@code SAMLRequest} parameter that will accompany this AuthNRequest
-		 *
-		 * @param samlRequest the SAMLRequest parameter.
-		 * @return this object
-		 */
-		public T samlRequest(String samlRequest) {
-			this.samlRequest = samlRequest;
-			return _this();
-		}
-
-		/**
-		 * Sets the {@code authenticationRequestUri}, a URL that will receive the AuthNRequest message
-		 *
-		 * @param authenticationRequestUri the relay state value, unencoded.
-		 * @return this object
-		 */
-		public T authenticationRequestUri(String authenticationRequestUri) {
-			this.authenticationRequestUri = authenticationRequestUri;
-			return _this();
-		}
-	}
-
-}

+ 12 - 62
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationRequestFactory.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2020 the original author or authors.
+ * Copyright 2002-2019 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.
@@ -16,25 +16,17 @@
 
 package org.springframework.security.saml2.provider.service.authentication;
 
-import org.joda.time.DateTime;
 import org.opensaml.saml.common.xml.SAMLConstants;
+import org.springframework.util.Assert;
+
+import org.joda.time.DateTime;
 import org.opensaml.saml.saml2.core.AuthnRequest;
 import org.opensaml.saml.saml2.core.Issuer;
-import org.springframework.security.saml2.credentials.Saml2X509Credential;
-import org.springframework.security.saml2.provider.service.authentication.Saml2RedirectAuthenticationRequest.Builder;
-import org.springframework.util.Assert;
 
 import java.time.Clock;
 import java.time.Instant;
-import java.util.List;
-import java.util.Map;
 import java.util.UUID;
 
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static java.util.Collections.emptyList;
-import static org.springframework.security.saml2.provider.service.authentication.Saml2Utils.samlDeflate;
-import static org.springframework.security.saml2.provider.service.authentication.Saml2Utils.samlEncode;
-
 /**
  * @since 5.2
  */
@@ -43,50 +35,11 @@ public class OpenSamlAuthenticationRequestFactory implements Saml2Authentication
 	private final OpenSamlImplementation saml = OpenSamlImplementation.getInstance();
 	private String protocolBinding = SAMLConstants.SAML2_POST_BINDING_URI;
 
-	@Override
-	@Deprecated
-	public String createAuthenticationRequest(Saml2AuthenticationRequest request) {
-		return createAuthenticationRequest(request, request.getCredentials());
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	@Override
-	public Saml2PostAuthenticationRequest createPostAuthenticationRequest(Saml2AuthenticationRequestContext context) {
-		String xml = createAuthenticationRequest(context, context.getRelyingPartyRegistration().getSigningCredentials());
-		return Saml2PostAuthenticationRequest.withAuthenticationRequestContext(context)
-				.samlRequest(samlEncode(xml.getBytes(UTF_8)))
-				.build();
-	}
-
 	/**
 	 * {@inheritDoc}
 	 */
 	@Override
-	public Saml2RedirectAuthenticationRequest createRedirectAuthenticationRequest(Saml2AuthenticationRequestContext context) {
-		String xml = createAuthenticationRequest(context, emptyList());
-		List<Saml2X509Credential> signingCredentials = context.getRelyingPartyRegistration().getSigningCredentials();
-		Builder result = Saml2RedirectAuthenticationRequest.withAuthenticationRequestContext(context);
-
-		String deflatedAndEncoded = samlEncode(samlDeflate(xml));
-		Map<String, String> signedParams = this.saml.signQueryParameters(
-				signingCredentials,
-				deflatedAndEncoded,
-				context.getRelayState()
-		);
-		result.samlRequest(signedParams.get("SAMLRequest"))
-				.relayState(signedParams.get("RelayState"))
-				.sigAlg(signedParams.get("SigAlg"))
-				.signature(signedParams.get("Signature"));
-		return result.build();
-	}
-
-	private String createAuthenticationRequest(Saml2AuthenticationRequestContext request, List<Saml2X509Credential> credentials) {
-		return createAuthenticationRequest(Saml2AuthenticationRequest.withAuthenticationRequestContext(request).build(), credentials);
-	}
-
-	private String createAuthenticationRequest(Saml2AuthenticationRequest context, List<Saml2X509Credential> credentials) {
+	public String createAuthenticationRequest(Saml2AuthenticationRequest request) {
 		AuthnRequest auth = this.saml.buildSAMLObject(AuthnRequest.class);
 		auth.setID("ARQ" + UUID.randomUUID().toString().substring(1));
 		auth.setIssueInstant(new DateTime(this.clock.millis()));
@@ -94,14 +47,14 @@ public class OpenSamlAuthenticationRequestFactory implements Saml2Authentication
 		auth.setIsPassive(Boolean.FALSE);
 		auth.setProtocolBinding(protocolBinding);
 		Issuer issuer = this.saml.buildSAMLObject(Issuer.class);
-		issuer.setValue(context.getIssuer());
+		issuer.setValue(request.getIssuer());
 		auth.setIssuer(issuer);
-		auth.setDestination(context.getDestination());
-		auth.setAssertionConsumerServiceURL(context.getAssertionConsumerServiceUrl());
+		auth.setDestination(request.getDestination());
+		auth.setAssertionConsumerServiceURL(request.getAssertionConsumerServiceUrl());
 		return this.saml.toXml(
 				auth,
-				credentials,
-				context.getIssuer()
+				request.getCredentials(),
+				request.getIssuer()
 		);
 	}
 
@@ -118,14 +71,11 @@ public class OpenSamlAuthenticationRequestFactory implements Saml2Authentication
 	}
 
 	/**
-	 * Sets the {@code protocolBinding} to use when generating authentication requests.
+	 * Sets the {@code protocolBinding} to use when generating authentication requests
 	 * Acceptable values are {@link SAMLConstants#SAML2_POST_BINDING_URI} and
 	 * {@link SAMLConstants#SAML2_REDIRECT_BINDING_URI}
-	 * The IDP will be reading this value in the {@code AuthNRequest} to determine how to
-	 * send the Response/Assertion to the ACS URL, assertion consumer service URL.
 	 *
-	 * @param protocolBinding either {@link SAMLConstants#SAML2_POST_BINDING_URI} or
-	 * {@link SAMLConstants#SAML2_REDIRECT_BINDING_URI}
+	 * @param protocolBinding
 	 * @throws IllegalArgumentException if the protocolBinding is not valid
 	 */
 	public void setProtocolBinding(String protocolBinding) {

+ 6 - 70
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlImplementation.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2020 the original author or authors.
+ * Copyright 2002-2019 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.
@@ -13,9 +13,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package org.springframework.security.saml2.provider.service.authentication;
 
+import org.springframework.security.saml2.Saml2Exception;
+import org.springframework.security.saml2.credentials.Saml2X509Credential;
+
 import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
 import net.shibboleth.utilities.java.support.xml.BasicParserPool;
 import net.shibboleth.utilities.java.support.xml.SerializeSupport;
@@ -39,7 +41,6 @@ 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;
@@ -47,29 +48,21 @@ import org.opensaml.xmlsec.encryption.support.SimpleRetrievalMethodEncryptedKeyR
 import org.opensaml.xmlsec.signature.support.SignatureConstants;
 import org.opensaml.xmlsec.signature.support.SignatureException;
 import org.opensaml.xmlsec.signature.support.SignatureSupport;
-import org.springframework.security.saml2.Saml2Exception;
-import org.springframework.security.saml2.credentials.Saml2X509Credential;
-import org.springframework.security.saml2.provider.service.authentication.Saml2Utils;
-import org.springframework.util.Assert;
-import org.springframework.web.util.UriUtils;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
-import javax.xml.XMLConstants;
-import javax.xml.namespace.QName;
 import java.io.ByteArrayInputStream;
-import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
-import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
 
 import static java.lang.Boolean.FALSE;
 import static java.lang.Boolean.TRUE;
 import static java.util.Arrays.asList;
 import static org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport.getBuilderFactory;
-import static org.springframework.util.StringUtils.hasText;
 
 /**
  * @since 5.2
@@ -198,68 +191,11 @@ final class OpenSamlImplementation {
 		}
 	}
 
-	/**
-	 * 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(
-			List<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) {

+ 3 - 17
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationRequest.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2020 the original author or authors.
+ * Copyright 2002-2019 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.
@@ -29,10 +29,9 @@ import java.util.function.Consumer;
  * from the service provider to the identity provider
  * https://www.oasis-open.org/committees/download.php/35711/sstc-saml-core-errata-2.0-wd-06-diff.pdf (line 2031)
  *
+ * @see {@link Saml2AuthenticationRequestFactory}
  * @since 5.2
- * @deprecated use {@link Saml2AuthenticationRequestContext}
  */
-@Deprecated
 public final class Saml2AuthenticationRequest {
 	private final String issuer;
 	private final List<Saml2X509Credential> credentials;
@@ -56,6 +55,7 @@ public final class Saml2AuthenticationRequest {
 				this.credentials.add(c);
 			}
 		}
+		Assert.notEmpty(this.credentials, "at least one SIGNING credential must be present");
 	}
 
 
@@ -104,20 +104,6 @@ public final class Saml2AuthenticationRequest {
 		return new Builder();
 	}
 
-	/**
-	 * A builder for {@link Saml2AuthenticationRequest}.
-	 * @param context a context object to copy values from.
-	 * returns a builder object
-	 */
-	public static Builder withAuthenticationRequestContext(Saml2AuthenticationRequestContext context) {
-		return new Builder()
-				.assertionConsumerServiceUrl(context.getAssertionConsumerServiceUrl())
-				.issuer(context.getIssuer())
-				.destination(context.getDestination())
-				.credentials(c -> c.addAll(context.getRelyingPartyRegistration().getCredentials()))
-				;
-	}
-
 	/**
 	 * A builder for {@link Saml2AuthenticationRequest}.
 	 */

+ 0 - 172
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationRequestContext.java

@@ -1,172 +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 org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
-import org.springframework.util.Assert;
-
-/**
- * Data holder for information required to create an {@code AuthNRequest}
- * to be sent from the service provider to the identity provider
- * <a href="https://www.oasis-open.org/committees/download.php/35711/sstc-saml-core-errata-2.0-wd-06-diff.pdf">
- * Assertions and Protocols for SAML 2 (line 2031)</a>
- *
- * @see Saml2AuthenticationRequestFactory#createPostAuthenticationRequest(Saml2AuthenticationRequestContext)
- * @see Saml2AuthenticationRequestFactory#createRedirectAuthenticationRequest(Saml2AuthenticationRequestContext)
- * @since 5.3
- */
-public final class Saml2AuthenticationRequestContext {
-	private final RelyingPartyRegistration relyingPartyRegistration;
-	private final String issuer;
-	private final String assertionConsumerServiceUrl;
-	private final String relayState;
-
-	private Saml2AuthenticationRequestContext(
-			RelyingPartyRegistration relyingPartyRegistration,
-			String issuer,
-			String assertionConsumerServiceUrl,
-			String relayState) {
-		Assert.hasText(issuer, "issuer cannot be null or empty");
-		Assert.notNull(relyingPartyRegistration, "relyingPartyRegistration cannot be null");
-		Assert.hasText(assertionConsumerServiceUrl, "spAssertionConsumerServiceUrl cannot be null or empty");
-		this.issuer = issuer;
-		this.relyingPartyRegistration = relyingPartyRegistration;
-		this.assertionConsumerServiceUrl = assertionConsumerServiceUrl;
-		this.relayState = relayState;
-	}
-
-	/**
-	 * Returns the {@link RelyingPartyRegistration} configuration for which the AuthNRequest is intended for.
-	 * @return the {@link RelyingPartyRegistration} configuration
-	 */
-	public RelyingPartyRegistration getRelyingPartyRegistration() {
-		return this.relyingPartyRegistration;
-	}
-
-	/**
-	 * Returns the {@code Issuer} value to be used in the {@code AuthNRequest} object.
-	 * This property should be used to populate the {@code AuthNRequest.Issuer} XML element.
-	 * This value typically is a URI, but can be an arbitrary string.
-	 * @return the Issuer value
-	 */
-	public String getIssuer() {
-		return this.issuer;
-	}
-
-	/**
-	 * Returns the desired {@code AssertionConsumerServiceUrl} that this SP wishes to receive the
-	 * assertion on. The IDP may or may not honor this request.
-	 * This property populates the {@code AuthNRequest.AssertionConsumerServiceURL} XML attribute.
-	 * @return the AssertionConsumerServiceURL value
-	 */
-	public String getAssertionConsumerServiceUrl() {
-		return assertionConsumerServiceUrl;
-	}
-
-	/**
-	 * Returns the RelayState value, if present in the parameters
-	 * @return the RelayState value, or null if not available
-	 */
-	public String getRelayState() {
-		return this.relayState;
-	}
-
-	/**
-	 * Returns the {@code Destination}, the WEB Single Sign On URI, for this authentication request.
-	 * This property can also populate the {@code AuthNRequest.Destination} XML attribute.
-	 * @return the Destination value
-	 */
-	public String getDestination() {
-		return this.getRelyingPartyRegistration().getIdpWebSsoUrl();
-	}
-
-	/**
-	 * A builder for {@link Saml2AuthenticationRequestContext}.
-	 * @return a builder object
-	 */
-	public static Builder builder() {
-		return new Builder();
-	}
-
-	/**
-	 * A builder for {@link Saml2AuthenticationRequestContext}.
-	 */
-	public static class Builder {
-		private String issuer;
-		private String assertionConsumerServiceUrl;
-		private String relayState;
-		private RelyingPartyRegistration relyingPartyRegistration;
-
-		private Builder() {
-		}
-
-		/**
-		 * Sets the issuer for the authentication request.
-		 * @param issuer - a required value
-		 * @return this {@code Builder}
-		 */
-		public Builder issuer(String issuer) {
-			this.issuer = issuer;
-			return this;
-		}
-
-		/**
-		 * Sets the {@link RelyingPartyRegistration} used to build the authentication request.
-		 * @param relyingPartyRegistration - a required value
-		 * @return this {@code Builder}
-		 */
-		public Builder relyingPartyRegistration(RelyingPartyRegistration relyingPartyRegistration) {
-			this.relyingPartyRegistration = relyingPartyRegistration;
-			return this;
-		}
-
-		/**
-		 * Sets the {@code assertionConsumerServiceURL} for the authentication request.
-		 * Typically the {@code Service Provider EntityID}
-		 * @param assertionConsumerServiceUrl - a required value
-		 * @return this {@code Builder}
-		 */
-		public Builder assertionConsumerServiceUrl(String assertionConsumerServiceUrl) {
-			this.assertionConsumerServiceUrl = assertionConsumerServiceUrl;
-			return this;
-		}
-
-		/**
-		 * Sets the {@code RelayState} parameter that will accompany this AuthNRequest
-		 * @param relayState the relay state value, unencoded. if null or empty, the parameter will be removed from the map.
-		 * @return this object
-		 */
-		public Builder relayState(String relayState) {
-			this.relayState = relayState;
-			return this;
-		}
-
-		/**
-		 * Creates a {@link Saml2AuthenticationRequestContext} object.
-		 * @return the Saml2AuthenticationRequest object
-		 * @throws {@link IllegalArgumentException} if a required property is not set
-		 */
-		public Saml2AuthenticationRequestContext build() {
-			return new Saml2AuthenticationRequestContext(
-					this.relyingPartyRegistration,
-					this.issuer,
-					this.assertionConsumerServiceUrl,
-					this.relayState
-			);
-		}
-	}
-}

+ 9 - 86
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationRequestFactory.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2020 the original author or authors.
+ * Copyright 2002-2019 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.
@@ -17,102 +17,25 @@
 package org.springframework.security.saml2.provider.service.authentication;
 
 import org.springframework.security.saml2.Saml2Exception;
-import org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType;
-import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
-
-import java.nio.charset.StandardCharsets;
-
-import static org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationRequest.withAuthenticationRequestContext;
-import static org.springframework.security.saml2.provider.service.authentication.Saml2Utils.samlDeflate;
-import static org.springframework.security.saml2.provider.service.authentication.Saml2Utils.samlEncode;
 
 /**
- * Component that generates AuthenticationRequest, <code>samlp:AuthnRequestType</code> XML, and accompanying
- * signature data.
- * as defined by https://www.oasis-open.org/committees/download.php/35711/sstc-saml-core-errata-2.0-wd-06-diff.pdf
+ * Component that generates an AuthenticationRequest, <code>samlp:AuthnRequestType</code> as defined by
+ * https://www.oasis-open.org/committees/download.php/35711/sstc-saml-core-errata-2.0-wd-06-diff.pdf
  * Page 50, Line 2147
  *
  * @since 5.2
  */
 public interface Saml2AuthenticationRequestFactory {
-
 	/**
-	 * Creates an authentication request from the Service Provider, sp, to the Identity Provider, idp.
+	 * Creates an authentication request from the Service Provider, sp,
+	 * to the Identity Provider, idp.
 	 * The authentication result is an XML string that may be signed, encrypted, both or neither.
-	 * This method only returns the {@code SAMLRequest} string for the request, and for a complete
-	 * set of data parameters please use {@link #createRedirectAuthenticationRequest(Saml2AuthenticationRequestContext)}
-	 * or {@link #createPostAuthenticationRequest(Saml2AuthenticationRequestContext)}
 	 *
-	 * @param request information about the identity provider,
-	 * the recipient of this authentication request and accompanying data
-	 * @return XML data in the format of a String. This data may be signed, encrypted, both signed and encrypted with the
-	 * signature embedded in the XML or neither signed and encrypted
+	 * @param request - information about the identity provider, the recipient of this authentication request and
+	 *                accompanying data
+	 * @return XML data in the format of a String. This data may be signed, encrypted, both signed and encrypted or
+	 * neither signed and encrypted
 	 * @throws Saml2Exception when a SAML library exception occurs
-	 * @since 5.2
-	 * @deprecated please use {@link #createRedirectAuthenticationRequest(Saml2AuthenticationRequestContext)}
-	 * or {@link #createPostAuthenticationRequest(Saml2AuthenticationRequestContext)}
-	 * This method will be removed in future versions of Spring Security
 	 */
-	@Deprecated
 	String createAuthenticationRequest(Saml2AuthenticationRequest request);
-
-	/**
-	 * Creates all the necessary AuthNRequest parameters for a REDIRECT binding.
-	 * If the {@link Saml2AuthenticationRequestContext} doesn't contain any {@link Saml2X509CredentialType#SIGNING} credentials
-	 * the result will not contain any signatures.
-	 * The data set will be signed and encoded for REDIRECT binding including the DEFLATE encoding.
-	 * It will contain the following parameters to be sent as part of the query string:
-	 * {@code SAMLRequest, RelayState, SigAlg, Signature}.
-	 * <i>The default implementation, for sake of backwards compatibility, of this method returns the
-	 * SAMLRequest message with an XML signature embedded, that should only be used for the{@link Saml2MessageBinding#POST}
-	 * binding, but works over {@link Saml2MessageBinding#POST} with most providers.</i>
-	 * @param context - information about the identity provider, the recipient of this authentication request and
-	 * accompanying data
-	 * @return a {@link Saml2RedirectAuthenticationRequest} object with applicable http parameters
-	 * necessary to make the AuthNRequest over a POST or REDIRECT binding.
-	 * All parameters will be SAML encoded/deflated, but escaped, ie URI encoded or encoded for Form Data.
-	 * @throws Saml2Exception when a SAML library exception occurs
-	 * @since 5.3
-	 */
-	default Saml2RedirectAuthenticationRequest createRedirectAuthenticationRequest(
-			Saml2AuthenticationRequestContext context
-	) {
-		//backwards compatible with 5.2.x settings
-		Saml2AuthenticationRequest.Builder resultBuilder = withAuthenticationRequestContext(context);
-		String samlRequest = createAuthenticationRequest(resultBuilder.build());
-		samlRequest = samlEncode(samlDeflate(samlRequest));
-		return Saml2RedirectAuthenticationRequest.withAuthenticationRequestContext(context)
-				.samlRequest(samlRequest)
-				.build();
-	}
-
-
-	/**
-	 * Creates all the necessary AuthNRequest parameters for a POST binding.
-	 * If the {@link Saml2AuthenticationRequestContext} doesn't contain any {@link Saml2X509CredentialType#SIGNING} credentials
-	 * the result will not contain any signatures.
-	 * The data set will be signed and encoded for  POST binding and if applicable signed with XML signatures.
-	 * will contain the following parameters to be sent as part of the form data: {@code SAMLRequest, RelayState}.
-	 * <i>The default implementation of this method returns the SAMLRequest message with an XML signature embedded,
-	 * that should only be used for the {@link Saml2MessageBinding#POST} binding.</i>
-	 * @param context - information about the identity provider, the recipient of this authentication request and
-	 * accompanying data
-	 * @return a {@link Saml2PostAuthenticationRequest} object with applicable http parameters
-	 * necessary to make the AuthNRequest over a POST binding.
-	 * All parameters will be SAML encoded but not escaped for Form Data.
-	 * @throws Saml2Exception when a SAML library exception occurs
-	 * @since 5.3
-	 */
-	default Saml2PostAuthenticationRequest createPostAuthenticationRequest(
-			Saml2AuthenticationRequestContext context
-	) {
-		//backwards compatible with 5.2.x settings
-		Saml2AuthenticationRequest.Builder resultBuilder = withAuthenticationRequestContext(context);
-		String samlRequest = createAuthenticationRequest(resultBuilder.build());
-		samlRequest = samlEncode(samlRequest.getBytes(StandardCharsets.UTF_8));
-		return Saml2PostAuthenticationRequest.withAuthenticationRequestContext(context)
-				.samlRequest(samlRequest)
-				.build();
-	}
-
 }

+ 0 - 85
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2PostAuthenticationRequest.java

@@ -1,85 +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 org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
-
-import static org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding.POST;
-
-/**
- * Data holder for information required to send an {@code AuthNRequest} over a POST binding
- * from the service provider to the identity provider
- * https://www.oasis-open.org/committees/download.php/35711/sstc-saml-core-errata-2.0-wd-06-diff.pdf (line 2031)
- *
- * @see Saml2AuthenticationRequestFactory
- * @since 5.3
- */
-public class Saml2PostAuthenticationRequest extends AbstractSaml2AuthenticationRequest {
-
-	private Saml2PostAuthenticationRequest(
-			String samlRequest,
-			String relayState,
-			String authenticationRequestUri) {
-		super(samlRequest, relayState, authenticationRequestUri);
-	}
-
-	/**
-	 * @return {@link Saml2MessageBinding#POST}
-	 */
-	@Override
-	public Saml2MessageBinding getBinding() {
-		return POST;
-	}
-
-	/**
-	 * Constructs a {@link Builder} from a {@link Saml2AuthenticationRequestContext} object.
-	 * By default the {@link Saml2PostAuthenticationRequest#getAuthenticationRequestUri()} will be set to the
-	 * {@link Saml2AuthenticationRequestContext#getDestination()} value.
-	 * @param context input providing {@code Destination}, {@code RelayState}, and {@code Issuer} objects.
-	 * @return a modifiable builder object
-	 */
-	public static Builder withAuthenticationRequestContext(Saml2AuthenticationRequestContext context) {
-		return new Builder()
-				.authenticationRequestUri(context.getDestination())
-				.relayState(context.getRelayState())
-				;
-	}
-
-	/**
-	 * Builder class for a {@link Saml2PostAuthenticationRequest} object.
-	 */
-	public static class Builder extends AbstractSaml2AuthenticationRequest.Builder<Builder> {
-
-		private Builder() {
-			super();
-		}
-
-		/**
-		 * Constructs an immutable {@link Saml2PostAuthenticationRequest} object.
-		 * @return an immutable {@link Saml2PostAuthenticationRequest} object.
-		 */
-		public Saml2PostAuthenticationRequest build() {
-			return new Saml2PostAuthenticationRequest(
-					this.samlRequest,
-					this.relayState,
-					this.authenticationRequestUri
-			);
-		}
-	}
-
-
-}

+ 0 - 133
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2RedirectAuthenticationRequest.java

@@ -1,133 +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 org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
-
-import static org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding.REDIRECT;
-
-/**
- * Data holder for information required to send an {@code AuthNRequest} over a REDIRECT binding
- * from the service provider to the identity provider
- * https://www.oasis-open.org/committees/download.php/35711/sstc-saml-core-errata-2.0-wd-06-diff.pdf (line 2031)
- *
- * @see Saml2AuthenticationRequestFactory
- * @since 5.3
- */
-public class Saml2RedirectAuthenticationRequest extends AbstractSaml2AuthenticationRequest {
-
-	private final String sigAlg;
-	private final String signature;
-
-	private Saml2RedirectAuthenticationRequest(
-			String samlRequest,
-			String sigAlg,
-			String signature,
-			String relayState,
-			String authenticationRequestUri) {
-		super(samlRequest, relayState, authenticationRequestUri);
-		this.sigAlg = sigAlg;
-		this.signature = signature;
-	}
-
-	/**
-	 * Returns the SigAlg value for {@link Saml2MessageBinding#REDIRECT} requests
-	 * @return the SigAlg value
-	 */
-	public String getSigAlg() {
-		return this.sigAlg;
-	}
-
-	/**
-	 * Returns the Signature value for {@link Saml2MessageBinding#REDIRECT} requests
-	 * @return the Signature value
-	 */
-	public String getSignature() {
-		return this.signature;
-	}
-
-	/**
-     * @return {@link Saml2MessageBinding#REDIRECT}
-	 */
-	@Override
-	public Saml2MessageBinding getBinding() {
-		return REDIRECT;
-	}
-
-	/**
-	 * Constructs a {@link Saml2RedirectAuthenticationRequest.Builder} from a {@link Saml2AuthenticationRequestContext} object.
-	 * By default the {@link Saml2RedirectAuthenticationRequest#getAuthenticationRequestUri()} will be set to the
-	 * {@link Saml2AuthenticationRequestContext#getDestination()} value.
-	 * @param context input providing {@code Destination}, {@code RelayState}, and {@code Issuer} objects.
-	 * @return a modifiable builder object
-	 */
-	public static Builder withAuthenticationRequestContext(Saml2AuthenticationRequestContext context) {
-		return new Builder()
-				.authenticationRequestUri(context.getDestination())
-				.relayState(context.getRelayState())
-				;
-	}
-
-	/**
-	 * Builder class for a {@link Saml2RedirectAuthenticationRequest} object.
-	 */
-	public static class Builder extends AbstractSaml2AuthenticationRequest.Builder<Builder> {
-		private String sigAlg;
-		private String signature;
-
-		private Builder() {
-			super();
-		}
-
-		/**
-		 * Sets the {@code SigAlg} parameter that will accompany this AuthNRequest
-		 * @param sigAlg the SigAlg parameter value.
-		 * @return this object
-		 */
-		public Builder sigAlg(String sigAlg) {
-			this.sigAlg = sigAlg;
-			return _this();
-		}
-
-		/**
-		 * Sets the {@code Signature} parameter that will accompany this AuthNRequest
-		 * @param signature the Signature parameter value.
-		 * @return this object
-		 */
-		public Builder signature(String signature) {
-			this.signature = signature;
-			return _this();
-		}
-
-		/**
-		 * Constructs an immutable {@link Saml2RedirectAuthenticationRequest} object.
-		 * @return an immutable {@link Saml2RedirectAuthenticationRequest} object.
-		 */
-		public Saml2RedirectAuthenticationRequest build() {
-			return new Saml2RedirectAuthenticationRequest(
-					this.samlRequest,
-					this.sigAlg,
-					this.signature,
-					this.relayState,
-					this.authenticationRequestUri
-			);
-		}
-
-	}
-
-
-}

+ 0 - 73
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2Utils.java

@@ -1,73 +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 org.apache.commons.codec.binary.Base64;
-import org.springframework.security.saml2.Saml2Exception;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.zip.Deflater;
-import java.util.zip.DeflaterOutputStream;
-import java.util.zip.Inflater;
-import java.util.zip.InflaterOutputStream;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static java.util.zip.Deflater.DEFLATED;
-
-/**
- * @since 5.3
- */
-final class Saml2Utils {
-
-
-	private static Base64 BASE64 = new Base64(0, new byte[]{'\n'});
-
-	static String samlEncode(byte[] b) {
-		return BASE64.encodeAsString(b);
-	}
-
-	static byte[] samlDecode(String s) {
-		return BASE64.decode(s);
-	}
-
-	static byte[] samlDeflate(String s) {
-		try {
-			ByteArrayOutputStream b = new ByteArrayOutputStream();
-			DeflaterOutputStream deflater = new DeflaterOutputStream(b, new Deflater(DEFLATED, true));
-			deflater.write(s.getBytes(UTF_8));
-			deflater.finish();
-			return b.toByteArray();
-		}
-		catch (IOException e) {
-			throw new Saml2Exception("Unable to deflate string", e);
-		}
-	}
-
-	static String samlInflate(byte[] b) {
-		try {
-			ByteArrayOutputStream out = new ByteArrayOutputStream();
-			InflaterOutputStream iout = new InflaterOutputStream(out, new Inflater(true));
-			iout.write(b);
-			iout.finish();
-			return new String(out.toByteArray(), UTF_8);
-		}
-		catch (IOException e) {
-			throw new Saml2Exception("Unable to inflate string", e);
-		}
-	}
-}

+ 0 - 45
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/Saml2MessageBinding.java

@@ -1,45 +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.registration;
-
-/**
- * The type of bindings that messages are exchanged using
- * Supported bindings are {@code urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST}
- * and {@code urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect}.
- * In addition there is support for {@code urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect}
- * with an XML signature in the message rather than query parameters.
- * @since 5.3
- */
-public enum Saml2MessageBinding {
-
-	POST("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"),
-	REDIRECT("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect");
-
-	private final String urn;
-
-	Saml2MessageBinding(String s) {
-		this.urn = s;
-	}
-
-	/**
-	 * Returns the URN value from the SAML 2 specification for this binding.
-	 * @return URN value representing this binding
-	 */
-	public String getUrn() {
-		return urn;
-	}
-}

+ 0 - 88
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2ServletUtils.java

@@ -1,88 +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.servlet.filter;
-
-import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
-import org.springframework.util.StringUtils;
-import org.springframework.web.util.UriComponents;
-import org.springframework.web.util.UriComponentsBuilder;
-
-import javax.servlet.http.HttpServletRequest;
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.springframework.security.web.util.UrlUtils.buildFullRequestUrl;
-import static org.springframework.web.util.UriComponentsBuilder.fromHttpUrl;
-
-/**
- * @since 5.3
- */
-final class Saml2ServletUtils {
-
-	private static final char PATH_DELIMITER = '/';
-
-	static String getServiceProviderEntityId(RelyingPartyRegistration rp, HttpServletRequest request) {
-		return resolveUrlTemplate(
-				rp.getLocalEntityIdTemplate(),
-				getApplicationUri(request),
-				rp.getRemoteIdpEntityId(),
-				rp.getRegistrationId()
-		);
-	}
-
-	static String resolveUrlTemplate(String template, String baseUrl, String entityId, String registrationId) {
-		if (!StringUtils.hasText(template)) {
-			return baseUrl;
-		}
-
-		Map<String, String> uriVariables = new HashMap<>();
-		UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl(baseUrl)
-				.replaceQuery(null)
-				.fragment(null)
-				.build();
-		String scheme = uriComponents.getScheme();
-		uriVariables.put("baseScheme", scheme == null ? "" : scheme);
-		String host = uriComponents.getHost();
-		uriVariables.put("baseHost", host == null ? "" : host);
-		// following logic is based on HierarchicalUriComponents#toUriString()
-		int port = uriComponents.getPort();
-		uriVariables.put("basePort", port == -1 ? "" : ":" + port);
-		String path = uriComponents.getPath();
-		if (StringUtils.hasLength(path)) {
-			if (path.charAt(0) != PATH_DELIMITER) {
-				path = PATH_DELIMITER + path;
-			}
-		}
-		uriVariables.put("basePath", path == null ? "" : path);
-		uriVariables.put("baseUrl", uriComponents.toUriString());
-		uriVariables.put("entityId", StringUtils.hasText(entityId) ? entityId : "");
-		uriVariables.put("registrationId", StringUtils.hasText(registrationId) ? registrationId : "");
-
-		return UriComponentsBuilder.fromUriString(template)
-				.buildAndExpand(uriVariables)
-				.toUriString();
-	}
-
-	static String getApplicationUri(HttpServletRequest request) {
-		UriComponents uriComponents = fromHttpUrl(buildFullRequestUrl(request))
-				.replacePath(request.getContextPath())
-				.replaceQuery(null)
-				.fragment(null)
-				.build();
-		return uriComponents.toUriString();
-	}
-}

+ 68 - 8
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2Utils.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2020 the original author or authors.
+ * Copyright 2002-2019 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.
@@ -18,34 +18,43 @@ package org.springframework.security.saml2.provider.service.servlet.filter;
 
 import org.apache.commons.codec.binary.Base64;
 import org.springframework.security.saml2.Saml2Exception;
+import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
+import org.springframework.util.StringUtils;
+import org.springframework.web.util.UriComponents;
+import org.springframework.web.util.UriComponentsBuilder;
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.zip.Deflater;
 import java.util.zip.DeflaterOutputStream;
 import java.util.zip.Inflater;
 import java.util.zip.InflaterOutputStream;
+import javax.servlet.http.HttpServletRequest;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static java.util.zip.Deflater.DEFLATED;
+import static org.springframework.security.web.util.UrlUtils.buildFullRequestUrl;
+import static org.springframework.web.util.UriComponentsBuilder.fromHttpUrl;
 
 /**
- * @since 5.3
+ * @since 5.2
  */
 final class Saml2Utils {
 
+	private static final char PATH_DELIMITER = '/';
+	private static org.apache.commons.codec.binary.Base64 BASE64 = new Base64(0, new byte[]{'\n'});
 
-	private static Base64 BASE64 = new Base64(0, new byte[]{'\n'});
-
-	static String samlEncode(byte[] b) {
+	static String encode(byte[] b) {
 		return BASE64.encodeAsString(b);
 	}
 
-	static byte[] samlDecode(String s) {
+	static byte[] decode(String s) {
 		return BASE64.decode(s);
 	}
 
-	static byte[] samlDeflate(String s) {
+	static byte[] deflate(String s) {
 		try {
 			ByteArrayOutputStream b = new ByteArrayOutputStream();
 			DeflaterOutputStream deflater = new DeflaterOutputStream(b, new Deflater(DEFLATED, true));
@@ -58,7 +67,7 @@ final class Saml2Utils {
 		}
 	}
 
-	static String samlInflate(byte[] b) {
+	static String inflate(byte[] b) {
 		try {
 			ByteArrayOutputStream out = new ByteArrayOutputStream();
 			InflaterOutputStream iout = new InflaterOutputStream(out, new Inflater(true));
@@ -70,4 +79,55 @@ final class Saml2Utils {
 			throw new Saml2Exception("Unable to inflate string", e);
 		}
 	}
+
+	static String getServiceProviderEntityId(RelyingPartyRegistration rp, HttpServletRequest request) {
+		return resolveUrlTemplate(
+				rp.getLocalEntityIdTemplate(),
+				getApplicationUri(request),
+				rp.getRemoteIdpEntityId(),
+				rp.getRegistrationId()
+		);
+	}
+
+	static String resolveUrlTemplate(String template, String baseUrl, String entityId, String registrationId) {
+		if (!StringUtils.hasText(template)) {
+			return baseUrl;
+		}
+
+		Map<String, String> uriVariables = new HashMap<>();
+		UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl(baseUrl)
+				.replaceQuery(null)
+				.fragment(null)
+				.build();
+		String scheme = uriComponents.getScheme();
+		uriVariables.put("baseScheme", scheme == null ? "" : scheme);
+		String host = uriComponents.getHost();
+		uriVariables.put("baseHost", host == null ? "" : host);
+		// following logic is based on HierarchicalUriComponents#toUriString()
+		int port = uriComponents.getPort();
+		uriVariables.put("basePort", port == -1 ? "" : ":" + port);
+		String path = uriComponents.getPath();
+		if (StringUtils.hasLength(path)) {
+			if (path.charAt(0) != PATH_DELIMITER) {
+				path = PATH_DELIMITER + path;
+			}
+		}
+		uriVariables.put("basePath", path == null ? "" : path);
+		uriVariables.put("baseUrl", uriComponents.toUriString());
+		uriVariables.put("entityId", StringUtils.hasText(entityId) ? entityId : "");
+		uriVariables.put("registrationId", StringUtils.hasText(registrationId) ? registrationId : "");
+
+		return UriComponentsBuilder.fromUriString(template)
+				.buildAndExpand(uriVariables)
+				.toUriString();
+	}
+
+	static String getApplicationUri(HttpServletRequest request) {
+		UriComponents uriComponents = fromHttpUrl(buildFullRequestUrl(request))
+				.replacePath(request.getContextPath())
+				.replaceQuery(null)
+				.fragment(null)
+				.build();
+		return uriComponents.toUriString();
+	}
 }

+ 5 - 5
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2WebSsoAuthenticationFilter.java

@@ -61,8 +61,8 @@ public class Saml2WebSsoAuthenticationFilter extends AbstractAuthenticationProce
 	 * @param filterProcessesUrl the processing URL, must contain a {registrationId} variable. Required.
 	 */
 	public Saml2WebSsoAuthenticationFilter(
-			RelyingPartyRegistrationRepository relyingPartyRegistrationRepository,
-			String filterProcessesUrl) {
+				RelyingPartyRegistrationRepository relyingPartyRegistrationRepository,
+				String filterProcessesUrl) {
 		super(filterProcessesUrl);
 		Assert.notNull(relyingPartyRegistrationRepository, "relyingPartyRegistrationRepository cannot be null");
 		Assert.hasText(filterProcessesUrl, "filterProcessesUrl must contain a URL pattern");
@@ -86,7 +86,7 @@ public class Saml2WebSsoAuthenticationFilter extends AbstractAuthenticationProce
 	public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
 			throws AuthenticationException {
 		String saml2Response = request.getParameter("SAMLResponse");
-		byte[] b = Saml2Utils.samlDecode(saml2Response);
+		byte[] b = Saml2Utils.decode(saml2Response);
 
 		String responseXml = inflateIfRequired(request, b);
 		String registrationId = this.matcher.matcher(request).getVariables().get("registrationId");
@@ -97,7 +97,7 @@ public class Saml2WebSsoAuthenticationFilter extends AbstractAuthenticationProce
 					"Relying Party Registration not found with ID: " + registrationId);
 			throw new Saml2AuthenticationException(saml2Error);
 		}
-		String localSpEntityId = Saml2ServletUtils.getServiceProviderEntityId(rp, request);
+		String localSpEntityId = Saml2Utils.getServiceProviderEntityId(rp, request);
 		final Saml2AuthenticationToken authentication = new Saml2AuthenticationToken(
 				responseXml,
 				request.getRequestURL().toString(),
@@ -110,7 +110,7 @@ public class Saml2WebSsoAuthenticationFilter extends AbstractAuthenticationProce
 
 	private String inflateIfRequired(HttpServletRequest request, byte[] b) {
 		if (HttpMethod.GET.matches(request.getMethod())) {
-			return Saml2Utils.samlInflate(b);
+			return Saml2Utils.inflate(b);
 		}
 		else {
 			return new String(b, UTF_8);

+ 30 - 35
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2WebSsoAuthenticationRequestFilter.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2020 the original author or authors.
+ * Copyright 2002-2019 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.
@@ -17,28 +17,29 @@
 package org.springframework.security.saml2.provider.service.servlet.filter;
 
 import org.springframework.security.saml2.provider.service.authentication.OpenSamlAuthenticationRequestFactory;
-import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationRequestContext;
+import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationRequest;
 import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationRequestFactory;
-import org.springframework.security.saml2.provider.service.authentication.Saml2RedirectAuthenticationRequest;
 import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
 import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
 import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
 import org.springframework.security.web.util.matcher.RequestMatcher;
 import org.springframework.security.web.util.matcher.RequestMatcher.MatchResult;
 import org.springframework.util.Assert;
+import org.springframework.util.StringUtils;
 import org.springframework.web.filter.OncePerRequestFilter;
 import org.springframework.web.util.UriComponentsBuilder;
 import org.springframework.web.util.UriUtils;
 
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 import javax.servlet.FilterChain;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
 
 import static java.lang.String.format;
-import static java.nio.charset.StandardCharsets.ISO_8859_1;
-import static org.springframework.util.StringUtils.hasText;
+import static org.springframework.security.saml2.provider.service.servlet.filter.Saml2Utils.deflate;
+import static org.springframework.security.saml2.provider.service.servlet.filter.Saml2Utils.encode;
 
 /**
  * @since 5.2
@@ -46,7 +47,9 @@ import static org.springframework.util.StringUtils.hasText;
 public class Saml2WebSsoAuthenticationRequestFilter extends OncePerRequestFilter {
 
 	private final RelyingPartyRegistrationRepository relyingPartyRegistrationRepository;
+
 	private RequestMatcher redirectMatcher = new AntPathRequestMatcher("/saml2/authenticate/{registrationId}");
+
 	private Saml2AuthenticationRequestFactory authenticationRequestFactory = new OpenSamlAuthenticationRequestFactory();
 
 	public Saml2WebSsoAuthenticationRequestFilter(RelyingPartyRegistrationRepository relyingPartyRegistrationRepository) {
@@ -88,47 +91,39 @@ public class Saml2WebSsoAuthenticationRequestFilter extends OncePerRequestFilter
 	}
 
 	private String createSamlRequestRedirectUrl(HttpServletRequest request, RelyingPartyRegistration relyingParty) {
-		Saml2AuthenticationRequestContext authnRequest = createRedirectAuthenticationRequestContext(relyingParty, request);
-		Saml2RedirectAuthenticationRequest authNData =
-				this.authenticationRequestFactory.createRedirectAuthenticationRequest(authnRequest);
-		UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(authNData.getAuthenticationRequestUri());
-		addParameter("SAMLRequest", authNData.getSamlRequest(), uriBuilder);
-		addParameter("RelayState", authNData.getRelayState(), uriBuilder);
-		addParameter("SigAlg", authNData.getSigAlg(), uriBuilder);
-		addParameter("Signature", authNData.getSignature(), uriBuilder);
+		Saml2AuthenticationRequest authNRequest = createAuthenticationRequest(relyingParty, request);
+		String xml = this.authenticationRequestFactory.createAuthenticationRequest(authNRequest);
+		String encoded = encode(deflate(xml));
+		String relayState = request.getParameter("RelayState");
+		UriComponentsBuilder uriBuilder = UriComponentsBuilder
+				.fromUriString(relyingParty.getIdpWebSsoUrl())
+				.queryParam("SAMLRequest", UriUtils.encode(encoded, StandardCharsets.ISO_8859_1));
+
+		if (StringUtils.hasText(relayState)) {
+			uriBuilder.queryParam("RelayState", UriUtils.encode(relayState, StandardCharsets.ISO_8859_1));
+		}
+
 		return uriBuilder
 				.build(true)
 				.toUriString();
 	}
 
-	private void addParameter(String name, String value, UriComponentsBuilder builder) {
-		Assert.hasText(name, "name cannot be empty or null");
-		if (hasText(value)) {
-			builder.queryParam(
-					UriUtils.encode(name, ISO_8859_1),
-					UriUtils.encode(value, ISO_8859_1)
-			);
-		}
-	}
-
-	private Saml2AuthenticationRequestContext createRedirectAuthenticationRequestContext(
-			RelyingPartyRegistration relyingParty,
-			HttpServletRequest request) {
-		String localSpEntityId = Saml2ServletUtils.getServiceProviderEntityId(relyingParty, request);
-		return Saml2AuthenticationRequestContext
+	private Saml2AuthenticationRequest createAuthenticationRequest(RelyingPartyRegistration relyingParty, HttpServletRequest request) {
+		String localSpEntityId = Saml2Utils.getServiceProviderEntityId(relyingParty, request);
+		return Saml2AuthenticationRequest
 				.builder()
 				.issuer(localSpEntityId)
-				.relyingPartyRegistration(relyingParty)
+				.destination(relyingParty.getIdpWebSsoUrl())
+				.credentials(c -> c.addAll(relyingParty.getCredentials()))
 				.assertionConsumerServiceUrl(
-						Saml2ServletUtils.resolveUrlTemplate(
+						Saml2Utils.resolveUrlTemplate(
 								relyingParty.getAssertionConsumerServiceUrlTemplate(),
-								Saml2ServletUtils.getApplicationUri(request),
+								Saml2Utils.getApplicationUri(request),
 								relyingParty.getRemoteIdpEntityId(),
 								relyingParty.getRegistrationId()
 						)
 				)
-				.relayState(request.getParameter("RelayState"))
-				.build()
-				;
+				.build();
 	}
+
 }

+ 11 - 59
saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationRequestFactoryTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2020 the original author or authors.
+ * Copyright 2002-2019 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.
@@ -23,77 +23,39 @@ import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.opensaml.saml.common.xml.SAMLConstants;
 import org.opensaml.saml.saml2.core.AuthnRequest;
-import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
-import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
 
-import java.nio.charset.StandardCharsets;
-
-import static org.assertj.core.api.Assertions.assertThat;
 import static org.hamcrest.CoreMatchers.containsString;
-import static org.springframework.security.saml2.provider.service.authentication.Saml2Utils.samlDecode;
 import static org.springframework.security.saml2.provider.service.authentication.TestSaml2X509Credentials.relyingPartyCredentials;
-import static org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding.POST;
-import static org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding.REDIRECT;
 
-/**
- * Tests for {@link OpenSamlAuthenticationRequestFactory}
- */
 public class OpenSamlAuthenticationRequestFactoryTests {
 
 	private OpenSamlAuthenticationRequestFactory factory;
-	private Saml2AuthenticationRequestContext.Builder contextBuilder;
-	private Saml2AuthenticationRequestContext context;
+	private Saml2AuthenticationRequest request;
 
 	@Rule
 	public ExpectedException exception = ExpectedException.none();
 
 	@Before
 	public void setUp() {
-		RelyingPartyRegistration registration = RelyingPartyRegistration.withRegistrationId("id")
-				.assertionConsumerServiceUrlTemplate("template")
-				.idpWebSsoUrl("https://destination/sso")
-				.remoteIdpEntityId("remote-entity-id")
-				.localEntityIdTemplate("local-entity-id")
+		request = Saml2AuthenticationRequest.builder()
+				.issuer("https://issuer")
+				.destination("https://destination/sso")
+				.assertionConsumerServiceUrl("https://issuer/sso")
 				.credentials(c -> c.addAll(relyingPartyCredentials()))
 				.build();
-		contextBuilder = Saml2AuthenticationRequestContext.builder()
-				.issuer("https://issuer")
-				.relyingPartyRegistration(registration)
-				.assertionConsumerServiceUrl("https://issuer/sso");
-		context = contextBuilder.build();
 		factory = new OpenSamlAuthenticationRequestFactory();
 	}
 
-	@Test
-	public void createAuthenticationRequestWhenInvokingDeprecatedMethodThenReturnsXML() {
-		Saml2AuthenticationRequest request = Saml2AuthenticationRequest.withAuthenticationRequestContext(context).build();
-		String result = factory.createAuthenticationRequest(request);
-		assertThat(result).startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<saml2p:AuthnRequest");
-	}
-
-	@Test
-	public void createRedirectAuthenticationRequestWhenUsingContextThenAllValuesAreSet() {
-		context = contextBuilder
-				.relayState("Relay State Value")
-				.build();
-		Saml2RedirectAuthenticationRequest result = factory.createRedirectAuthenticationRequest(context);
-		assertThat(result.getSamlRequest()).isNotEmpty();
-		assertThat(result.getRelayState()).isEqualTo("Relay State Value");
-		assertThat(result.getSigAlg()).isNotEmpty();
-		assertThat(result.getSignature()).isNotEmpty();
-		assertThat(result.getBinding()).isEqualTo(REDIRECT);
-	}
-
 	@Test
 	public void createAuthenticationRequestWhenDefaultThenReturnsPostBinding() {
-		AuthnRequest authn = getAuthNRequest(POST);
+		AuthnRequest authn = getAuthNRequest();
 		Assert.assertEquals(SAMLConstants.SAML2_POST_BINDING_URI, authn.getProtocolBinding());
 	}
 
 	@Test
 	public void createAuthenticationRequestWhenSetUriThenReturnsCorrectBinding() {
 		factory.setProtocolBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI);
-		AuthnRequest authn = getAuthNRequest(POST);
+		AuthnRequest authn = getAuthNRequest();
 		Assert.assertEquals(SAMLConstants.SAML2_REDIRECT_BINDING_URI, authn.getProtocolBinding());
 	}
 
@@ -104,18 +66,8 @@ public class OpenSamlAuthenticationRequestFactoryTests {
 		factory.setProtocolBinding("my-invalid-binding");
 	}
 
-	private AuthnRequest getAuthNRequest(Saml2MessageBinding binding) {
-		AbstractSaml2AuthenticationRequest result = (binding == REDIRECT) ?
-				factory.createRedirectAuthenticationRequest(context) :
-				factory.createPostAuthenticationRequest(context);
-		String samlRequest = result.getSamlRequest();
-		assertThat(samlRequest).isNotEmpty();
-		if (result.getBinding() == REDIRECT) {
-			samlRequest = Saml2Utils.samlInflate(samlDecode(samlRequest));
-		}
-		else {
-			samlRequest = new String(samlDecode(samlRequest), StandardCharsets.UTF_8);
-		}
-		return (AuthnRequest) OpenSamlImplementation.getInstance().resolve(samlRequest);
+	private AuthnRequest getAuthNRequest() {
+		String xml = factory.createAuthenticationRequest(request);
+		return (AuthnRequest) OpenSamlImplementation.getInstance().resolve(xml);
 	}
 }

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

@@ -17,23 +17,6 @@
 package org.springframework.security.saml2.provider.service.authentication;
 
 import org.junit.Test;
-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.xmlsec.crypto.XMLSigningUtil;
-import org.springframework.security.saml2.credentials.Saml2X509Credential;
-import org.springframework.web.util.UriUtils;
-
-import java.util.List;
-import java.util.Map;
-
-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.TestSaml2X509Credentials.assertingPartyCredentials;
-import static org.springframework.security.saml2.provider.service.authentication.TestSaml2X509Credentials.relyingPartyCredentials;
 
 public class OpenSamlImplementationTests {
 
@@ -41,42 +24,4 @@ public class OpenSamlImplementationTests {
 	public void getInstance() {
 		OpenSamlImplementation.getInstance();
 	}
-
-	@Test
-	public void signQueryParametersWhenDataSuppliedReturnsValidSignature() throws Exception {
-		OpenSamlImplementation impl = OpenSamlImplementation.getInstance();
-		List<Saml2X509Credential> signCredentials = relyingPartyCredentials();
-		List<Saml2X509Credential> verifyCredentials = assertingPartyCredentials();
-		String samlRequest = "saml-request-example";
-		String encoded = Saml2Utils.samlEncode(samlRequest.getBytes(UTF_8));
-		String relayState = "test relay state";
-		Map<String, String> parameters = impl.signQueryParameters(signCredentials, 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(
-				getOpenSamlCredential(verifyCredentials.get(1), "local-sp-entity-id", UsageType.SIGNING),
-				ALGO_ID_SIGNATURE_RSA_SHA256,
-				signature,
-				queryString.getBytes(UTF_8)
-		);
-		assertThat(result).isTrue();
-	}
-
-	private Credential getOpenSamlCredential(Saml2X509Credential credential, String localSpEntityId, UsageType usageType) {
-		BasicCredential cred = CredentialSupport.getSimpleCredential(
-				credential.getCertificate(),
-				credential.getPrivateKey()
-		);
-		cred.setEntityId(localSpEntityId);
-		cred.setUsageType(usageType);
-		return cred;
-	}
 }

+ 0 - 72
saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationRequestFactoryTests.java

@@ -1,72 +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 org.junit.Test;
-import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
-
-import java.util.UUID;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.springframework.security.saml2.provider.service.authentication.Saml2Utils.samlDecode;
-import static org.springframework.security.saml2.provider.service.authentication.Saml2Utils.samlInflate;
-import static org.springframework.security.saml2.provider.service.authentication.TestSaml2X509Credentials.relyingPartyCredentials;
-
-/**
- * Tests for {@link Saml2AuthenticationRequestFactory} default interface methods
- */
-public class Saml2AuthenticationRequestFactoryTests {
-
-	private RelyingPartyRegistration registration = RelyingPartyRegistration.withRegistrationId("id")
-			.assertionConsumerServiceUrlTemplate("template")
-			.idpWebSsoUrl("https://example.com/destination")
-			.remoteIdpEntityId("remote-entity-id")
-			.localEntityIdTemplate("local-entity-id")
-			.credentials(c -> c.addAll(relyingPartyCredentials()))
-			.build();
-
-	@Test
-	public void createAuthenticationRequestParametersWhenRedirectDefaultIsUsedMessageIsDeflatedAndEncoded() {
-		final String value = "Test String: "+ UUID.randomUUID().toString();
-		Saml2AuthenticationRequestFactory factory = request -> value;
-		Saml2AuthenticationRequestContext request = Saml2AuthenticationRequestContext.builder()
-				.relyingPartyRegistration(registration)
-				.issuer("https://example.com/issuer")
-				.assertionConsumerServiceUrl("https://example.com/acs-url")
-				.build();
-		Saml2RedirectAuthenticationRequest response = factory.createRedirectAuthenticationRequest(request);
-		String resultValue = response.getSamlRequest();
-		byte[] decoded = samlDecode(resultValue);
-		String inflated = samlInflate(decoded);
-		assertThat(inflated).isEqualTo(value);
-	}
-
-	@Test
-	public void createAuthenticationRequestParametersWhenPostDefaultIsUsedMessageIsEncoded() {
-		final String value = "Test String: "+ UUID.randomUUID().toString();
-		Saml2AuthenticationRequestFactory factory = request -> value;
-		Saml2AuthenticationRequestContext request = Saml2AuthenticationRequestContext.builder()
-				.relyingPartyRegistration(registration)
-				.issuer("https://example.com/issuer")
-				.assertionConsumerServiceUrl("https://example.com/acs-url")
-				.build();
-		Saml2PostAuthenticationRequest response = factory.createPostAuthenticationRequest(request);
-		String resultValue = response.getSamlRequest();
-		byte[] decoded = samlDecode(resultValue);
-		assertThat(new String(decoded)).isEqualTo(value);
-	}
-}

+ 2 - 2
saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2UtilsTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2020 the original author or authors.
+ * Copyright 2002-2019 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.
@@ -50,7 +50,7 @@ public class Saml2UtilsTests {
 	@Test
 	public void decodeWhenUsingSamlUtilsBase64ThenXmlIsValid() throws Exception {
 		String responseUrlDecoded = getSsoCircleEncodedXml();
-		String xml = new String(Saml2Utils.samlDecode(responseUrlDecoded), UTF_8);
+		String xml = new String(Saml2Utils.decode(responseUrlDecoded), UTF_8);
 		validateSsoCircleXml(xml);
 	}
 

+ 29 - 50
saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2WebSsoAuthenticationRequestFilterTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2020 the original author or authors.
+ * Copyright 2002-2019 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.
@@ -17,9 +17,10 @@
 package org.springframework.security.saml2.provider.service.servlet.filter;
 
 import java.io.IOException;
-import java.nio.charset.StandardCharsets;
 import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletResponse;
 
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.springframework.mock.web.MockFilterChain;
@@ -27,22 +28,18 @@ import org.springframework.mock.web.MockHttpServletRequest;
 import org.springframework.mock.web.MockHttpServletResponse;
 import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
 import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
-import org.springframework.web.util.UriUtils;
 
-import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 import static org.springframework.security.saml2.provider.service.servlet.filter.TestSaml2SigningCredentials.signingCredential;
 
 public class Saml2WebSsoAuthenticationRequestFilterTests {
 
-	private static final String IDP_SSO_URL = "https://sso-url.example.com/IDP/SSO";
 	private Saml2WebSsoAuthenticationRequestFilter filter;
 	private RelyingPartyRegistrationRepository repository = mock(RelyingPartyRegistrationRepository.class);
 	private MockHttpServletRequest request;
-	private MockHttpServletResponse response;
+	private HttpServletResponse response;
 	private MockFilterChain filterChain;
-	private RelyingPartyRegistration.Builder rpBuilder;
 
 	@Before
 	public void setup() {
@@ -52,61 +49,43 @@ public class Saml2WebSsoAuthenticationRequestFilterTests {
 		request.setPathInfo("/saml2/authenticate/registration-id");
 
 		filterChain = new MockFilterChain();
+	}
 
-		rpBuilder = RelyingPartyRegistration
+	@Test
+	public void createSamlRequestRedirectUrlAndReturnUrlWithoutRelayState() throws ServletException, IOException {
+		RelyingPartyRegistration relyingPartyRegistration = RelyingPartyRegistration
 				.withRegistrationId("registration-id")
 				.remoteIdpEntityId("idp-entity-id")
-				.idpWebSsoUrl(IDP_SSO_URL)
+				.idpWebSsoUrl("sso-url")
 				.assertionConsumerServiceUrlTemplate("template")
-				.credentials(c -> c.add(signingCredential()));
-	}
+				.credentials(c -> c.add(signingCredential()))
+				.build();
+
+		when(repository.findByRegistrationId("registration-id"))
+				.thenReturn(relyingPartyRegistration);
 
-	@Test
-	public void doFilterWhenNoRelayStateThenRedirectDoesNotContainParameter() throws ServletException, IOException {
-		when(repository.findByRegistrationId("registration-id")).thenReturn(rpBuilder.build());
 		filter.doFilterInternal(request, response, filterChain);
-		assertThat(response.getHeader("Location"))
-				.doesNotContain("RelayState=")
-				.startsWith(IDP_SSO_URL);
+
+		Assert.assertFalse(response.getHeader("Location").contains("RelayState="));
 	}
 
 	@Test
-	public void doFilterWhenRelayStateThenRedirectDoesContainParameter() throws ServletException, IOException {
-		when(repository.findByRegistrationId("registration-id")).thenReturn(rpBuilder.build());
+	public void createSamlRequestRedirectUrlAndReturnUrlWithRelayState() throws ServletException, IOException {
+		RelyingPartyRegistration relyingPartyRegistration = RelyingPartyRegistration
+				.withRegistrationId("registration-id")
+				.remoteIdpEntityId("idp-entity-id")
+				.idpWebSsoUrl("sso-url")
+				.assertionConsumerServiceUrlTemplate("template")
+				.credentials(c -> c.add(signingCredential()))
+				.build();
+
+		when(repository.findByRegistrationId("registration-id"))
+				.thenReturn(relyingPartyRegistration);
+
 		request.setParameter("RelayState", "my-relay-state");
-		filter.doFilterInternal(request, response, filterChain);
-		assertThat(response.getHeader("Location"))
-				.contains("RelayState=my-relay-state")
-				.startsWith(IDP_SSO_URL);
-	}
 
-	@Test
-	public void doFilterWhenRelayStateThatRequiresEncodingThenRedirectDoesContainsEncodedParameter() throws Exception {
-		when(repository.findByRegistrationId("registration-id")).thenReturn(rpBuilder.build());
-		final String relayStateValue = "https://my-relay-state.example.com?with=param&other=param";
-		final String relayStateEncoded = UriUtils.encode(relayStateValue, StandardCharsets.ISO_8859_1);
-		request.setParameter("RelayState", relayStateValue);
 		filter.doFilterInternal(request, response, filterChain);
-		assertThat(response.getHeader("Location"))
-				.contains("RelayState="+relayStateEncoded)
-				.startsWith(IDP_SSO_URL);
-	}
 
-	@Test
-	public void doFilterWhenSimpleSignatureSpecifiedThenSignatureParametersAreInTheRedirectURL() throws Exception {
-		when(repository.findByRegistrationId("registration-id")).thenReturn(
-				rpBuilder
-						.build()
-		);
-		final String relayStateValue = "https://my-relay-state.example.com?with=param&other=param";
-		final String relayStateEncoded = UriUtils.encode(relayStateValue, StandardCharsets.ISO_8859_1);
-		request.setParameter("RelayState", relayStateValue);
-		filter.doFilterInternal(request, response, filterChain);
-		assertThat(response.getHeader("Location"))
-				.contains("RelayState="+relayStateEncoded)
-				.contains("SigAlg=")
-				.contains("Signature=")
-				.startsWith(IDP_SSO_URL);
+		Assert.assertTrue(response.getHeader("Location").contains("RelayState=my-relay-state"));
 	}
-
 }

+ 52 - 6
samples/boot/saml2login/src/integration-test/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlActionTestingSupport.java → samples/boot/saml2login/src/integration-test/java/org/springframework/security/samples/OpenSamlActionTestingSupport.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2020 the original author or authors.
+ * Copyright 2002-2019 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.
@@ -14,9 +14,12 @@
  * limitations under the License.
  */
 
-package org.springframework.security.saml2.provider.service.authentication;
+package org.springframework.security.samples;
+
+import org.springframework.security.saml2.Saml2Exception;
 
 import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import org.apache.commons.codec.binary.Base64;
 import org.apache.xml.security.algorithms.JCEMapper;
 import org.apache.xml.security.encryption.XMLCipherParameters;
 import org.joda.time.DateTime;
@@ -54,16 +57,23 @@ import org.opensaml.security.credential.CredentialSupport;
 import org.opensaml.xmlsec.encryption.support.DataEncryptionParameters;
 import org.opensaml.xmlsec.encryption.support.EncryptionException;
 import org.opensaml.xmlsec.encryption.support.KeyEncryptionParameters;
-import org.springframework.security.saml2.Saml2Exception;
 
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import javax.crypto.SecretKey;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
 import java.security.NoSuchAlgorithmException;
 import java.security.NoSuchProviderException;
 import java.security.cert.X509Certificate;
+import java.util.zip.Deflater;
+import java.util.zip.DeflaterOutputStream;
+import java.util.zip.Inflater;
+import java.util.zip.InflaterOutputStream;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.crypto.SecretKey;
 
+import static java.nio.charset.StandardCharsets.UTF_8;
 import static java.util.Arrays.asList;
+import static java.util.zip.Deflater.DEFLATED;
 import static org.opensaml.security.crypto.KeySupport.generateKey;
 
 /**
@@ -73,6 +83,8 @@ import static org.opensaml.security.crypto.KeySupport.generateKey;
  */
 public class OpenSamlActionTestingSupport {
 
+	static Base64 UNCHUNKED_ENCODER = new Base64(0, new byte[] { '\n' });
+
 	/** ID used for all generated {@link Response} objects. */
 	final static String REQUEST_ID = "request";
 
@@ -82,6 +94,40 @@ public class OpenSamlActionTestingSupport {
 	/** ID used for all generated {@link Assertion} objects. */
 	final static String ASSERTION_ID = "assertion";
 
+	static String encode(byte[] b) {
+		return UNCHUNKED_ENCODER.encodeToString(b);
+	}
+
+	static byte[] decode(String s) {
+		return UNCHUNKED_ENCODER.decode(s);
+	}
+
+	static byte[] deflate(String s) {
+		try {
+			ByteArrayOutputStream b = new ByteArrayOutputStream();
+			DeflaterOutputStream deflater = new DeflaterOutputStream(b, new Deflater(DEFLATED, true));
+			deflater.write(s.getBytes(UTF_8));
+			deflater.finish();
+			return b.toByteArray();
+		}
+		catch (IOException e) {
+			throw new Saml2Exception("Unable to deflate string", e);
+		}
+	}
+
+	static String inflate(byte[] b) {
+		try {
+			ByteArrayOutputStream out = new ByteArrayOutputStream();
+			InflaterOutputStream iout = new InflaterOutputStream(out, new Inflater(true));
+			iout.write(b);
+			iout.finish();
+			return new String(out.toByteArray(), UTF_8);
+		}
+		catch (IOException e) {
+			throw new Saml2Exception("Unable to inflate string", e);
+		}
+	}
+
 	static EncryptedAssertion encryptAssertion(Assertion assertion, X509Certificate certificate) {
 		Encrypter encrypter = getEncrypter(certificate);
 		try {

+ 14 - 19
samples/boot/saml2login/src/integration-test/java/org/springframework/security/saml2/provider/service/authentication/Saml2LoginIntegrationTests.java → samples/boot/saml2login/src/integration-test/java/org/springframework/security/samples/Saml2LoginIntegrationTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2020 the original author or authors.
+ * Copyright 2002-2019 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.
@@ -13,8 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-package org.springframework.security.saml2.provider.service.authentication;
+package org.springframework.security.samples;
 
 import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
 import net.shibboleth.utilities.java.support.xml.BasicParserPool;
@@ -53,6 +52,7 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
 import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.http.MediaType;
+import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationException;
 import org.springframework.test.context.junit4.SpringRunner;
 import org.springframework.test.util.AssertionErrors;
 import org.springframework.test.web.servlet.MockMvc;
@@ -63,7 +63,6 @@ import org.springframework.web.util.UriComponentsBuilder;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
-import javax.servlet.http.HttpSession;
 import java.io.ByteArrayInputStream;
 import java.net.URLDecoder;
 import java.nio.charset.StandardCharsets;
@@ -74,18 +73,19 @@ import java.security.cert.CertificateException;
 import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
 import java.util.UUID;
+import javax.servlet.http.HttpSession;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.equalTo;
-import static org.hamcrest.Matchers.matchesRegex;
 import static org.hamcrest.Matchers.startsWith;
-import static org.springframework.security.saml2.provider.service.authentication.OpenSamlActionTestingSupport.buildConditions;
-import static org.springframework.security.saml2.provider.service.authentication.OpenSamlActionTestingSupport.buildIssuer;
-import static org.springframework.security.saml2.provider.service.authentication.OpenSamlActionTestingSupport.buildSubject;
-import static org.springframework.security.saml2.provider.service.authentication.OpenSamlActionTestingSupport.buildSubjectConfirmation;
-import static org.springframework.security.saml2.provider.service.authentication.OpenSamlActionTestingSupport.buildSubjectConfirmationData;
-import static org.springframework.security.saml2.provider.service.authentication.OpenSamlActionTestingSupport.encryptNameId;
+import static org.springframework.security.samples.OpenSamlActionTestingSupport.buildConditions;
+import static org.springframework.security.samples.OpenSamlActionTestingSupport.buildIssuer;
+import static org.springframework.security.samples.OpenSamlActionTestingSupport.buildSubject;
+import static org.springframework.security.samples.OpenSamlActionTestingSupport.buildSubjectConfirmation;
+import static org.springframework.security.samples.OpenSamlActionTestingSupport.buildSubjectConfirmationData;
+import static org.springframework.security.samples.OpenSamlActionTestingSupport.encryptNameId;
+import static org.springframework.security.samples.OpenSamlActionTestingSupport.inflate;
 import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated;
 import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.unauthenticated;
 import static org.springframework.security.web.WebAttributes.AUTHENTICATION_EXCEPTION;
@@ -133,15 +133,10 @@ public class Saml2LoginIntegrationTests {
 		mockMvc.perform(
 				get("http://localhost:8080/saml2/authenticate/simplesamlphp")
 						.param("RelayState", "relay state value with spaces")
-						.param("OtherParam", "OtherParamValue")
-						.param("OtherParam2", "OtherParamValue2")
 		)
 				.andExpect(status().is3xxRedirection())
 				.andExpect(header().string("Location", startsWith("https://simplesaml-for-spring-saml.cfapps.io/saml2/idp/SSOService.php?SAMLRequest=")))
-				.andExpect(header().string("Location", containsString("RelayState=relay%20state%20value%20with%20spaces")))
-				//check order of parameters
-				.andExpect(header().string("Location", matchesRegex(".*\\?SAMLRequest\\=.*\\&RelayState\\=.*\\&SigAlg\\=.*\\&Signature\\=.*")));
-
+				.andExpect(header().string("Location", containsString("RelayState=relay%20state%20value%20with%20spaces")));
 	}
 
 	@Test
@@ -156,7 +151,7 @@ public class Saml2LoginIntegrationTests {
 		String request = parameters.getFirst("SAMLRequest");
 		AssertionErrors.assertNotNull("SAMLRequest parameter is missing", request);
 		request = URLDecoder.decode(request);
-		request = Saml2Utils.samlInflate(Saml2Utils.samlDecode(request));
+		request = inflate(OpenSamlActionTestingSupport.decode(request));
 		AuthnRequest authnRequest = (AuthnRequest) fromXml(request);
 		String destination = authnRequest.getDestination();
 		assertEquals(
@@ -303,7 +298,7 @@ public class Saml2LoginIntegrationTests {
 		String xml = toXml(response);
 		return mockMvc.perform(post("http://localhost:8080/login/saml2/sso/simplesamlphp")
 				.contentType(MediaType.APPLICATION_FORM_URLENCODED)
-				.param("SAMLResponse", Saml2Utils.samlEncode(xml.getBytes(UTF_8))))
+				.param("SAMLResponse", OpenSamlActionTestingSupport.encode(xml.getBytes(UTF_8))))
 				.andExpect(status().is3xxRedirection())
 				.andExpect(redirectedUrl(redirectUrl));
 	}