diff --git a/saml-core/src/main/java/org/keycloak/saml/BaseSAML2BindingBuilder.java b/saml-core/src/main/java/org/keycloak/saml/BaseSAML2BindingBuilder.java
index be74b74..38b0f1c 100755
--- a/saml-core/src/main/java/org/keycloak/saml/BaseSAML2BindingBuilder.java
+++ b/saml-core/src/main/java/org/keycloak/saml/BaseSAML2BindingBuilder.java
@@ -351,7 +351,6 @@ public class BaseSAML2BindingBuilder<T extends BaseSAML2BindingBuilder> {
public URI generateRedirectUri(String samlParameterName, String redirectUri, Document document) throws ConfigurationException, ProcessingException, IOException {
KeycloakUriBuilder builder = KeycloakUriBuilder.fromUri(redirectUri)
- .replaceQuery(null)
.queryParam(samlParameterName, base64Encoded(document));
if (relayState != null) {
builder.queryParam("RelayState", relayState);
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/BrokerTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/BrokerTest.java
index 85809fe..4c53d29 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/BrokerTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/BrokerTest.java
@@ -40,9 +40,13 @@ import org.keycloak.testsuite.updaters.IdentityProviderCreator;
import org.keycloak.testsuite.util.IdentityProviderBuilder;
import org.keycloak.testsuite.util.SamlClientBuilder;
import java.io.IOException;
+import java.net.URI;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
+import org.apache.http.Header;
+import org.apache.http.HttpHeaders;
+import org.hamcrest.Matchers;
import org.junit.Assert;
import org.junit.Test;
import static org.junit.Assert.assertThat;
@@ -59,13 +63,13 @@ import static org.keycloak.testsuite.util.SamlClient.Binding.REDIRECT;
*/
public class BrokerTest extends AbstractSamlTest {
- private IdentityProviderRepresentation addIdentityProvider() {
+ private IdentityProviderRepresentation addIdentityProvider(String samlEndpoint) {
IdentityProviderRepresentation identityProvider = IdentityProviderBuilder.create()
.providerId(SAMLIdentityProviderFactory.PROVIDER_ID)
.alias(SAML_BROKER_ALIAS)
.displayName("SAML")
- .setAttribute(SAMLIdentityProviderConfig.SINGLE_SIGN_ON_SERVICE_URL, "http://saml.idp/saml")
- .setAttribute(SAMLIdentityProviderConfig.SINGLE_LOGOUT_SERVICE_URL, "http://saml.idp/saml")
+ .setAttribute(SAMLIdentityProviderConfig.SINGLE_SIGN_ON_SERVICE_URL, samlEndpoint)
+ .setAttribute(SAMLIdentityProviderConfig.SINGLE_LOGOUT_SERVICE_URL, samlEndpoint)
.setAttribute(SAMLIdentityProviderConfig.NAME_ID_POLICY_FORMAT, JBossSAMLURIConstants.NAMEID_FORMAT_EMAIL.get())
.setAttribute(SAMLIdentityProviderConfig.POST_BINDING_RESPONSE, "false")
.setAttribute(SAMLIdentityProviderConfig.POST_BINDING_AUTHN_REQUEST, "false")
@@ -107,7 +111,7 @@ public class BrokerTest extends AbstractSamlTest {
AuthenticationExecutionInfoRepresentation reviewProfileAuthenticator = null;
String firstBrokerLoginFlowAlias = null;
- try (IdentityProviderCreator idp = new IdentityProviderCreator(realm, addIdentityProvider())) {
+ try (IdentityProviderCreator idp = new IdentityProviderCreator(realm, addIdentityProvider("http://saml.idp/saml"))) {
IdentityProviderRepresentation idpRepresentation = idp.identityProvider().toRepresentation();
firstBrokerLoginFlowAlias = idpRepresentation.getFirstBrokerLoginFlowAlias();
List<AuthenticationExecutionInfoRepresentation> executions = realm.flows().getExecutions(firstBrokerLoginFlowAlias);
@@ -153,4 +157,32 @@ public class BrokerTest extends AbstractSamlTest {
}
}
+ @Test
+ public void testRedirectQueryParametersPreserved() throws IOException {
+ final RealmResource realm = adminClient.realm(REALM_NAME);
+
+ try (IdentityProviderCreator idp = new IdentityProviderCreator(realm, addIdentityProvider("http://saml.idp/?service=name&serviceType=prod"))) {
+ SAMLDocumentHolder samlResponse = new SamlClientBuilder()
+ .authnRequest(getAuthServerSamlEndpoint(REALM_NAME), SAML_CLIENT_ID_SALES_POST, SAML_ASSERTION_CONSUMER_URL_SALES_POST, POST).build()
+ .login().idp(SAML_BROKER_ALIAS).build()
+
+ // Virtually perform login at IdP (return artificial SAML response)
+ .getSamlResponse(REDIRECT);
+
+ assertThat(samlResponse.getSamlObject(), Matchers.instanceOf(AuthnRequestType.class));
+ AuthnRequestType ar = (AuthnRequestType) samlResponse.getSamlObject();
+ assertThat(ar.getDestination(), Matchers.equalTo(URI.create("http://saml.idp/?service=name&serviceType=prod")));
+
+ Header[] headers = new SamlClientBuilder()
+ .authnRequest(getAuthServerSamlEndpoint(REALM_NAME), SAML_CLIENT_ID_SALES_POST, SAML_ASSERTION_CONSUMER_URL_SALES_POST, POST).build()
+ .login().idp(SAML_BROKER_ALIAS).build()
+ .doNotFollowRedirects()
+ .executeAndTransform(resp -> resp.getHeaders(HttpHeaders.LOCATION));
+
+ assertThat(headers.length, Matchers.is(1));
+ assertThat(headers[0].getValue(), Matchers.containsString("http://saml.idp/?service=name&serviceType=prod"));
+ assertThat(headers[0].getValue(), Matchers.containsString("SAMLRequest"));
+ }
+ }
+
}