From 5f0424fb1124fba84471af7ec1515d73575f167e Mon Sep 17 00:00:00 2001 From: stianst Date: Tue, 9 Oct 2018 15:13:37 +0200 Subject: [PATCH] KEYCLOAK-8310 Change scheme option to alwaysHttps option --- .../keycloak/url/FixedHostnameProvider.java | 14 +- .../url/FixedHostnameProviderFactory.java | 9 +- .../testsuite/url/FixedHostnameTest.java | 126 +++++++++++------- .../resources/META-INF/keycloak-server.json | 4 +- 4 files changed, 96 insertions(+), 57 deletions(-) diff --git a/services/src/main/java/org/keycloak/url/FixedHostnameProvider.java b/services/src/main/java/org/keycloak/url/FixedHostnameProvider.java index 0e31578ced..e438e87491 100644 --- a/services/src/main/java/org/keycloak/url/FixedHostnameProvider.java +++ b/services/src/main/java/org/keycloak/url/FixedHostnameProvider.java @@ -10,13 +10,13 @@ public class FixedHostnameProvider implements HostnameProvider { private final KeycloakSession session; private final String globalHostname; - private final String scheme; + private final boolean alwaysHttps; private final int httpPort; private final int httpsPort; - public FixedHostnameProvider(KeycloakSession session, String scheme, String globalHostname, int httpPort, int httpsPort) { + public FixedHostnameProvider(KeycloakSession session, boolean alwaysHttps, String globalHostname, int httpPort, int httpsPort) { this.session = session; - this.scheme = scheme; + this.alwaysHttps = alwaysHttps; this.globalHostname = globalHostname; this.httpPort = httpPort; this.httpsPort = httpsPort; @@ -24,7 +24,7 @@ public class FixedHostnameProvider implements HostnameProvider { @Override public String getScheme(UriInfo originalUriInfo) { - return scheme != null ? scheme : originalUriInfo.getRequestUri().getScheme(); + return alwaysHttps ? "https" : originalUriInfo.getRequestUri().getScheme(); } @Override @@ -50,6 +50,12 @@ public class FixedHostnameProvider implements HostnameProvider { } else { return httpsPort; } + } else if (alwaysHttps) { + if (httpsPort == 443) { + return -1; + } else { + return httpsPort; + } } else { if (httpPort == -1) { return originalUriInfo.getRequestUri().getPort(); diff --git a/services/src/main/java/org/keycloak/url/FixedHostnameProviderFactory.java b/services/src/main/java/org/keycloak/url/FixedHostnameProviderFactory.java index 25a030ee38..e7e96d906e 100644 --- a/services/src/main/java/org/keycloak/url/FixedHostnameProviderFactory.java +++ b/services/src/main/java/org/keycloak/url/FixedHostnameProviderFactory.java @@ -10,11 +10,11 @@ public class FixedHostnameProviderFactory implements HostnameProviderFactory { private String hostname; private int httpPort; private int httpsPort; - private String scheme; + private boolean alwaysHttps; @Override public HostnameProvider create(KeycloakSession session) { - return new FixedHostnameProvider(session, scheme, hostname, httpPort, httpsPort); + return new FixedHostnameProvider(session, alwaysHttps, hostname, httpPort, httpsPort); } @Override @@ -26,10 +26,7 @@ public class FixedHostnameProviderFactory implements HostnameProviderFactory { this.httpPort = config.getInt("httpPort", -1); this.httpsPort = config.getInt("httpsPort", -1); - this.scheme = config.get("scheme"); - if (scheme != null && scheme.trim().isEmpty()) { - scheme = null; - } + this.alwaysHttps = config.getBoolean("alwaysHttps", false); } @Override diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/url/FixedHostnameTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/url/FixedHostnameTest.java index 35381af3b3..1ece435c51 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/url/FixedHostnameTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/url/FixedHostnameTest.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import org.jboss.arquillian.container.test.api.ContainerController; import org.jboss.arquillian.test.api.ArquillianResource; +import org.junit.Before; import org.junit.Test; import org.keycloak.client.registration.Auth; import org.keycloak.client.registration.ClientRegistration; @@ -19,12 +20,11 @@ import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.testsuite.AbstractKeycloakTest; import org.keycloak.testsuite.arquillian.AuthServerTestEnricher; -import org.keycloak.testsuite.util.ClientBuilder; import org.keycloak.testsuite.util.OAuthClient; import org.wildfly.extras.creaper.core.online.OnlineManagementClient; import org.wildfly.extras.creaper.core.online.operations.admin.Administration; -import java.io.IOException; +import java.net.URISyntaxException; import java.util.HashMap; import java.util.List; @@ -37,6 +37,16 @@ public class FixedHostnameTest extends AbstractKeycloakTest { @ArquillianResource protected ContainerController controller; + String authServerUrl; + + String suiteScheme; + + @Before + public void before() throws URISyntaxException { + suiteScheme = suiteContext.getAuthServerInfo().getContextRoot().toURI().getScheme(); + authServerUrl = suiteContext.getAuthServerInfo().getContextRoot() + "/auth"; + } + @Override public void addTestRealms(List testRealms) { RealmRepresentation realm = loadJson(getClass().getResourceAsStream("/testrealm.json"), RealmRepresentation.class); @@ -56,55 +66,83 @@ public class FixedHostnameTest extends AbstractKeycloakTest { oauth.clientId("direct-grant"); try { - assertWellKnown("test", "http","localhost"); + assertWellKnown("test", suiteScheme + "://localhost:8180"); - configureFixedHostname(null); + configureFixedHostname(-1, -1, false); - assertWellKnown("test", "http","keycloak.127.0.0.1.nip.io"); - assertWellKnown("hostname", "http","custom-domain.127.0.0.1.nip.io"); + assertWellKnown("test", suiteScheme + "://keycloak.127.0.0.1.nip.io:8180"); + assertWellKnown("hostname", suiteScheme + "://custom-domain.127.0.0.1.nip.io:8180"); - assertTokenIssuer("test", "http","keycloak.127.0.0.1.nip.io"); - assertTokenIssuer("hostname", "http","custom-domain.127.0.0.1.nip.io"); + assertTokenIssuer("test", suiteScheme + "://keycloak.127.0.0.1.nip.io:8180"); + assertTokenIssuer("hostname", suiteScheme + "://custom-domain.127.0.0.1.nip.io:8180"); - assertInitialAccessTokenFromMasterRealm("test","http","keycloak.127.0.0.1.nip.io"); - assertInitialAccessTokenFromMasterRealm("hostname", "http","custom-domain.127.0.0.1.nip.io"); + assertInitialAccessTokenFromMasterRealm("test", suiteScheme + "://keycloak.127.0.0.1.nip.io:8180"); + assertInitialAccessTokenFromMasterRealm("hostname", suiteScheme + "://custom-domain.127.0.0.1.nip.io:8180"); } finally { clearFixedHostname(); } } @Test - public void fixedHostnameAndScheme() throws Exception { + public void fixedHttpPort() throws Exception { + // Make sure request are always sent with http + authServerUrl = authServerUrl.replace("https://", "http://"); + oauth.clientId("direct-grant"); try { - assertWellKnown("test", "http","localhost"); + assertWellKnown("test", suiteScheme + "://localhost:8180"); - configureFixedHostname("https"); + configureFixedHostname(80, -1, false); - assertWellKnown("test", "https","keycloak.127.0.0.1.nip.io"); - assertWellKnown("hostname", "https","custom-domain.127.0.0.1.nip.io"); + assertWellKnown("test", suiteScheme + "://keycloak.127.0.0.1.nip.io"); + assertWellKnown("hostname", suiteScheme + "://custom-domain.127.0.0.1.nip.io"); - assertTokenIssuer("test", "https","keycloak.127.0.0.1.nip.io"); - assertTokenIssuer("hostname", "https","custom-domain.127.0.0.1.nip.io"); + assertTokenIssuer("test", suiteScheme + "://keycloak.127.0.0.1.nip.io"); + assertTokenIssuer("hostname", suiteScheme + "://custom-domain.127.0.0.1.nip.io"); - assertInitialAccessTokenFromMasterRealm("test", "https", "keycloak.127.0.0.1.nip.io"); - assertInitialAccessTokenFromMasterRealm("hostname", "https", "custom-domain.127.0.0.1.nip.io"); + assertInitialAccessTokenFromMasterRealm("test", suiteScheme + "://keycloak.127.0.0.1.nip.io"); + assertInitialAccessTokenFromMasterRealm("hostname", suiteScheme + "://custom-domain.127.0.0.1.nip.io"); } finally { clearFixedHostname(); } } - private void assertInitialAccessTokenFromMasterRealm(String realm, String expectedScheme, String expectedHostname) throws JWSInputException, ClientRegistrationException { + @Test + public void fixedHostnameAlwaysHttpsHttpsPort() throws Exception { + // Make sure request are always sent with http + authServerUrl = authServerUrl.replace("https://", "http://"); + + oauth.clientId("direct-grant"); + + try { + assertWellKnown("test", suiteScheme + "://localhost:8180"); + + configureFixedHostname(-1, 443, true); + + assertWellKnown("test", "https://keycloak.127.0.0.1.nip.io"); + assertWellKnown("hostname", "https://custom-domain.127.0.0.1.nip.io"); + + assertTokenIssuer("test", "https://keycloak.127.0.0.1.nip.io"); + assertTokenIssuer("hostname", "https://custom-domain.127.0.0.1.nip.io"); + + assertInitialAccessTokenFromMasterRealm("test", "https://keycloak.127.0.0.1.nip.io"); + assertInitialAccessTokenFromMasterRealm("hostname", "https://custom-domain.127.0.0.1.nip.io"); + } finally { + clearFixedHostname(); + } + } + + private void assertInitialAccessTokenFromMasterRealm(String realm, String expectedBaseUrl) throws JWSInputException, ClientRegistrationException { ClientInitialAccessCreatePresentation rep = new ClientInitialAccessCreatePresentation(); rep.setCount(1); rep.setExpiration(10000); ClientInitialAccessPresentation initialAccess = adminClient.realm(realm).clientInitialAccess().create(rep); JsonWebToken token = new JWSInput(initialAccess.getToken()).readJsonContent(JsonWebToken.class); - assertEquals(expectedScheme + "://" + expectedHostname + ":8180/auth/realms/" + realm, token.getIssuer()); + assertEquals(expectedBaseUrl + "/auth/realms/" + realm, token.getIssuer()); - ClientRegistration clientReg = ClientRegistration.create().url(suiteContext.getAuthServerInfo().getContextRoot() + "/auth", realm).build(); + ClientRegistration clientReg = ClientRegistration.create().url(authServerUrl, realm).build(); clientReg.auth(Auth.token(initialAccess.getToken())); ClientRepresentation client = new ClientRepresentation(); @@ -113,34 +151,36 @@ public class FixedHostnameTest extends AbstractKeycloakTest { String registrationAccessToken = response.getRegistrationAccessToken(); JsonWebToken registrationToken = new JWSInput(registrationAccessToken).readJsonContent(JsonWebToken.class); - assertEquals(expectedScheme + "://" + expectedHostname + ":8180/auth/realms/" + realm, registrationToken.getIssuer()); + assertEquals(expectedBaseUrl + "/auth/realms/" + realm, registrationToken.getIssuer()); } - private void assertTokenIssuer(String realm, String expectedScheme, String expectedHostname) throws Exception { + private void assertTokenIssuer(String realm, String expectedBaseUrl) throws Exception { + oauth.baseUrl(authServerUrl); oauth.realm(realm); OAuthClient.AccessTokenResponse tokenResponse = oauth.doGrantAccessTokenRequest("password", "test-user@localhost", "password"); AccessToken token = new JWSInput(tokenResponse.getAccessToken()).readJsonContent(AccessToken.class); - assertEquals(expectedScheme + "://" + expectedHostname + ":8180/auth/realms/" + realm, token.getIssuer()); + assertEquals(expectedBaseUrl + "/auth/realms/" + realm, token.getIssuer()); String introspection = oauth.introspectAccessTokenWithClientCredential(oauth.getClientId(), "password", tokenResponse.getAccessToken()); ObjectMapper objectMapper = new ObjectMapper(); JsonNode introspectionNode = objectMapper.readTree(introspection); assertTrue(introspectionNode.get("active").asBoolean()); - assertEquals(expectedScheme + "://" + expectedHostname + ":8180/auth/realms/" + realm, introspectionNode.get("iss").asText()); + assertEquals(expectedBaseUrl + "/auth/realms/" + realm, introspectionNode.get("iss").asText()); } - private void assertWellKnown(String realm, String expectedScheme, String expectedHostname) { + private void assertWellKnown(String realm, String expectedBaseUrl) { + oauth.baseUrl(authServerUrl); OIDCConfigurationRepresentation config = oauth.doWellKnownRequest(realm); - assertEquals(expectedScheme + "://" + expectedHostname + ":8180/auth/realms/" + realm + "/protocol/openid-connect/token", config.getTokenEndpoint()); + assertEquals(expectedBaseUrl + "/auth/realms/" + realm + "/protocol/openid-connect/token", config.getTokenEndpoint()); } - private void configureFixedHostname(String scheme) throws Exception { + private void configureFixedHostname(int httpPort, int httpsPort, boolean alwaysHttps) throws Exception { if (suiteContext.getAuthServerInfo().isUndertow()) { - configureUndertow("fixed", "keycloak.127.0.0.1.nip.io", scheme); + configureUndertow("fixed", "keycloak.127.0.0.1.nip.io", httpPort, httpsPort, alwaysHttps); } else if (suiteContext.getAuthServerInfo().isJBossBased()) { - configureWildFly("fixed", "keycloak.127.0.0.1.nip.io", scheme); + configureWildFly("fixed", "keycloak.127.0.0.1.nip.io", httpPort, httpsPort, alwaysHttps); } else { throw new RuntimeException("Don't know how to config"); } @@ -151,9 +191,9 @@ public class FixedHostnameTest extends AbstractKeycloakTest { private void clearFixedHostname() throws Exception { if (suiteContext.getAuthServerInfo().isUndertow()) { - configureUndertow("request", "localhost", null); + configureUndertow("request", "localhost", -1, -1,false); } else if (suiteContext.getAuthServerInfo().isJBossBased()) { - configureWildFly("request", "localhost", null); + configureWildFly("request", "localhost", -1, -1, false); } else { throw new RuntimeException("Don't know how to config"); } @@ -161,31 +201,27 @@ public class FixedHostnameTest extends AbstractKeycloakTest { reconnectAdminClient(); } - private void configureUndertow(String provider, String hostname, String scheme) { + private void configureUndertow(String provider, String hostname, int httpPort, int httpsPort, boolean alwaysHttps) { controller.stop(suiteContext.getAuthServerInfo().getQualifier()); System.setProperty("keycloak.hostname.provider", provider); System.setProperty("keycloak.hostname.fixed.hostname", hostname); - if (scheme != null) { - System.setProperty("keycloak.hostname.fixed.scheme", scheme); - } else { - System.getProperties().remove("keycloak.hostname.fixed.scheme"); - } + System.setProperty("keycloak.hostname.fixed.httpPort", String.valueOf(httpPort)); + System.setProperty("keycloak.hostname.fixed.httpsPort", String.valueOf(httpsPort)); + System.setProperty("keycloak.hostname.fixed.alwaysHttps", String.valueOf(alwaysHttps)); controller.start(suiteContext.getAuthServerInfo().getQualifier()); } - private void configureWildFly(String provider, String hostname, String scheme) throws Exception { + private void configureWildFly(String provider, String hostname, int httpPort, int httpsPort, boolean alwaysHttps) throws Exception { OnlineManagementClient client = AuthServerTestEnricher.getManagementClient(); Administration administration = new Administration(client); client.execute("/subsystem=keycloak-server/spi=hostname:write-attribute(name=default-provider, value=" + provider + ")"); client.execute("/subsystem=keycloak-server/spi=hostname/provider=fixed:write-attribute(name=properties.hostname,value=" + hostname + ")"); - if (scheme != null) { - client.execute("/subsystem=keycloak-server/spi=hostname/provider=fixed:write-attribute(name=properties.scheme,value=" + scheme + ")"); - } else { - client.execute("/subsystem=keycloak-server/spi=hostname/provider=fixed:map-remove(name=properties,key=scheme)"); - } + client.execute("/subsystem=keycloak-server/spi=hostname/provider=fixed:write-attribute(name=properties.httpPort,value=" + httpPort + ")"); + client.execute("/subsystem=keycloak-server/spi=hostname/provider=fixed:write-attribute(name=properties.httpsPort,value=" + httpsPort + ")"); + client.execute("/subsystem=keycloak-server/spi=hostname/provider=fixed:write-attribute(name=properties.alwaysHttps,value=" + alwaysHttps + ")"); administration.reloadIfRequired(); diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/META-INF/keycloak-server.json b/testsuite/integration-arquillian/tests/base/src/test/resources/META-INF/keycloak-server.json index 3fd578e340..79ced07822 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/resources/META-INF/keycloak-server.json +++ b/testsuite/integration-arquillian/tests/base/src/test/resources/META-INF/keycloak-server.json @@ -6,8 +6,8 @@ "fixed": { "hostname": "${keycloak.hostname.fixed.hostname:localhost}", "httpPort": "${keycloak.hostname.fixed.httpPort:-1}", - "httpsPort": "${keycloak.hostname.fixed.httpPorts:-1}", - "scheme": "${keycloak.hostname.fixed.scheme:}" + "httpsPort": "${keycloak.hostname.fixed.httpsPort:-1}", + "alwaysHttps": "${keycloak.hostname.fixed.alwaysHttps:false}" } },