diff --git a/docs/guides/src/main/server/hostname.adoc b/docs/guides/src/main/server/hostname.adoc index 6e03388072..73e12dbf9a 100644 --- a/docs/guides/src/main/server/hostname.adoc +++ b/docs/guides/src/main/server/hostname.adoc @@ -55,6 +55,20 @@ To reduce attack surface, the administration endpoints for Keycloak and the Admi Therefore, you can secure them by using a reverse proxy. For more information about which paths to expose using a reverse proxy, see the <@links.server id="reverseproxy"/> Guide. +==== Exposing the administration console using a different hostname + +The administration console can be exposed using a hostname other than what you set to the frontend URLs via the `hostname` option. For that, +you can set the `hostname-admin` option as follows: + +<@kc.start parameters="--hostname=myurl --hostname-admin=myadminurl"/> + +When the `hostname-admin` option is set the URLs used by the administration console will have that hostname hardcoded in them. Otherwise, +the URLs used by the administration console are going to be based on the hostname from the request. + +If you don't set this option and the administration console is accessed using a hostname other than what is set to the frontend URLs, you +might get an error from the server telling you that the redirect URI used by the console is invalid. In this case, you should update the +`security-admin-console` client to add a valid redirect URI based on the hostname you want the administration console to be accessible. + == Overriding the hostname path When running Keycloak behind a reverse proxy, you may expose Keycloak using a different context path such as `myproxy.url/mykeycloak`. To perform this action, you can override the hostname path to use the path defined in your reverse proxyas shown in this example: diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/HostnamePropertyMappers.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/HostnamePropertyMappers.java index b5c76d0e03..ee43eedab4 100644 --- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/HostnamePropertyMappers.java +++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/HostnamePropertyMappers.java @@ -14,6 +14,11 @@ final class HostnamePropertyMappers { .description("Hostname for the Keycloak server.") .paramLabel("hostname") .build(), + builder().from("hostname-admin") + .to("kc.spi-hostname-default-admin") + .description("The hostname for accessing the administration console. Use this option if you are exposing the administration console using a hostname other than the value set to the 'hostname' option.") + .paramLabel("hostname") + .build(), builder().from("hostname-strict") .to("kc.spi-hostname-default-strict") .description("Disables dynamically resolving the hostname from request headers. Should always be set to true in production, unless proxy verifies the Host header.") diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/hostname/DefaultHostnameProvider.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/hostname/DefaultHostnameProvider.java index 6262af9d96..74887f1d7f 100644 --- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/hostname/DefaultHostnameProvider.java +++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/hostname/DefaultHostnameProvider.java @@ -79,7 +79,7 @@ public final class DefaultHostnameProvider implements HostnameProvider, Hostname } if (ADMIN.equals(urlType)) { - return getHostname(originalUriInfo); + return adminHostName == null ? getHostname(originalUriInfo) : adminHostName; } return fromFrontChannel(originalUriInfo, URI::getHost, this::getHostname, frontChannelHostName); diff --git a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/HostnameDistTest.java b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/HostnameDistTest.java index 658c860f67..bd12fb4275 100644 --- a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/HostnameDistTest.java +++ b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/HostnameDistTest.java @@ -110,6 +110,19 @@ public class HostnameDistTest { Assert.assertTrue(when().get("https://localhost:8443").asString().contains("https://localhost:8443/admin/")); } + @Test + @Launch({ "start-dev", "--hostname=mykeycloak.127.0.0.1.nip.io", "--hostname-admin=mykeycloakadmin.127.0.0.1.nip.io" }) + public void testHostnameAdminSet() { + Assert.assertTrue(when().get("https://mykeycloak.127.0.0.1.nip.io:8443/admin/master/console").asString().contains("var authUrl = 'https://mykeycloakadmin.127.0.0.1.nip.io:8443'")); + Assert.assertTrue(when().get("https://mykeycloak.127.0.0.1.nip.io:8443/realms/master/protocol/openid-connect/auth?client_id=security-admin-console&redirect_uri=https://mykeycloakadmin.127.0.0.1.nip.io:8443/admin/master/console&state=02234324-d91e-4bf2-8396-57498e96b12a&response_mode=fragment&response_type=code&scope=openid&nonce=f8f3812e-e349-4bbf-8d15-cbba4927f5e5&code_challenge=7qjD_v11WGkt1ig-ZFHxJdrEvuTlzjFRgRGQ_5ADcko&code_challenge_method=S256").asString().contains("Sign in to your account")); + } + + @Test + @Launch({ "start-dev", "--hostname=mykeycloak.127.0.0.1.nip.io" }) + public void testInvalidRedirectUriWhenAdminNotSet() { + Assert.assertTrue(when().get("https://mykeycloak.127.0.0.1.nip.io:8443/realms/master/protocol/openid-connect/auth?client_id=security-admin-console&redirect_uri=https://mykeycloakadmin.127.0.0.1.nip.io:8443/admin/master/console&state=02234324-d91e-4bf2-8396-57498e96b12a&response_mode=fragment&response_type=code&scope=openid&nonce=f8f3812e-e349-4bbf-8d15-cbba4927f5e5&code_challenge=7qjD_v11WGkt1ig-ZFHxJdrEvuTlzjFRgRGQ_5ADcko&code_challenge_method=S256").asString().contains("Invalid parameter: redirect_uri")); + } + private OIDCConfigurationRepresentation getServerMetadata(String baseUrl) { return when().get(baseUrl + "/realms/master/.well-known/openid-configuration").as(OIDCConfigurationRepresentation.class); } diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testStartDevHelp.unix.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testStartDevHelp.unix.approved.txt index 6b2adc08dc..df3fa65115 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testStartDevHelp.unix.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testStartDevHelp.unix.approved.txt @@ -46,6 +46,10 @@ Hostname: --hostname Hostname for the Keycloak server. +--hostname-admin + The hostname for accessing the administration console. Use this option if you + are exposing the administration console using a hostname other than the + value set to the 'hostname' option. --hostname-path This should be set if proxy uses a different context-path for Keycloak. --hostname-port diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testStartDevHelp.windows.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testStartDevHelp.windows.approved.txt index 609d146c81..62d32696be 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testStartDevHelp.windows.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testStartDevHelp.windows.approved.txt @@ -46,6 +46,10 @@ Hostname: --hostname Hostname for the Keycloak server. +--hostname-admin + The hostname for accessing the administration console. Use this option if you + are exposing the administration console using a hostname other than the + value set to the 'hostname' option. --hostname-path This should be set if proxy uses a different context-path for Keycloak. --hostname-port diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testStartDevHelpAll.unix.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testStartDevHelpAll.unix.approved.txt index 7aa90b4984..31fe756d6e 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testStartDevHelpAll.unix.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testStartDevHelpAll.unix.approved.txt @@ -73,6 +73,10 @@ Hostname: --hostname Hostname for the Keycloak server. +--hostname-admin + The hostname for accessing the administration console. Use this option if you + are exposing the administration console using a hostname other than the + value set to the 'hostname' option. --hostname-path This should be set if proxy uses a different context-path for Keycloak. --hostname-port diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testStartDevHelpAll.windows.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testStartDevHelpAll.windows.approved.txt index e8d0709269..01aa726e77 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testStartDevHelpAll.windows.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testStartDevHelpAll.windows.approved.txt @@ -73,6 +73,10 @@ Hostname: --hostname Hostname for the Keycloak server. +--hostname-admin + The hostname for accessing the administration console. Use this option if you + are exposing the administration console using a hostname other than the + value set to the 'hostname' option. --hostname-path This should be set if proxy uses a different context-path for Keycloak. --hostname-port diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testStartHelp.unix.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testStartHelp.unix.approved.txt index 5b5e0733ca..f101d27506 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testStartHelp.unix.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testStartHelp.unix.approved.txt @@ -49,6 +49,10 @@ Hostname: --hostname Hostname for the Keycloak server. +--hostname-admin + The hostname for accessing the administration console. Use this option if you + are exposing the administration console using a hostname other than the + value set to the 'hostname' option. --hostname-path This should be set if proxy uses a different context-path for Keycloak. --hostname-port diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testStartHelp.windows.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testStartHelp.windows.approved.txt index 1261fe646d..dfc3f35b05 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testStartHelp.windows.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/approvals/cli/help/HelpCommandTest.testStartHelp.windows.approved.txt @@ -49,6 +49,10 @@ Hostname: --hostname Hostname for the Keycloak server. +--hostname-admin + The hostname for accessing the administration console. Use this option if you + are exposing the administration console using a hostname other than the + value set to the 'hostname' option. --hostname-path This should be set if proxy uses a different context-path for Keycloak. --hostname-port