mirror of
https://github.com/keycloak/keycloak.git
synced 2026-01-09 23:12:06 -03:30
fix: adding checks around the hostname path (#43193)
closes: #43166 Signed-off-by: Steve Hawkins <shawkins@redhat.com>
This commit is contained in:
parent
bda0e2a67c
commit
aa04ff8781
@ -11,6 +11,7 @@ import java.util.stream.Stream;
|
||||
|
||||
import org.keycloak.common.Profile;
|
||||
import org.keycloak.config.HostnameV2Options;
|
||||
import org.keycloak.config.HttpOptions;
|
||||
import org.keycloak.quarkus.runtime.Environment;
|
||||
import org.keycloak.quarkus.runtime.cli.Picocli;
|
||||
import org.keycloak.quarkus.runtime.cli.command.AbstractCommand;
|
||||
@ -103,10 +104,30 @@ public final class HostnameV2PropertyMappers implements PropertyMapperGrouping {
|
||||
// else might be allowable if HOST is overwritten
|
||||
}
|
||||
|
||||
if (proxyHeaders == null && !url.getPath().isEmpty()
|
||||
&& Boolean.valueOf(Configuration.getConfigValue(HostnameV2Options.HOSTNAME_BACKCHANNEL_DYNAMIC).getValue())
|
||||
&& !normalizePath(url.getPath()).equals(
|
||||
normalizePath(Configuration.getConfigValue(HttpOptions.HTTP_RELATIVE_PATH).getValue()))) {
|
||||
warn.accept("Likely misconfiguration detected. When using a `hostname` that includes a path that does not match the `http-relative-path` you must use `proxy-headers` to properly detect backchannel requests.");
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (MalformedURLException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static String normalizePath(String path) {
|
||||
if (path == null) {
|
||||
return path;
|
||||
}
|
||||
if (!path.startsWith("/")) {
|
||||
path = "/" + path;
|
||||
}
|
||||
if (path.endsWith("/")) {
|
||||
path = path.substring(0, path.length() - 1);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -103,6 +103,16 @@ public class ProxyHostnameV2DistTest {
|
||||
cliResult.assertMessage(ADDRESS);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Launch({ "start-dev", "--hostname=https://mykeycloak.org:8443/path", "--proxy-headers=forwarded", "--hostname-backchannel-dynamic=true" })
|
||||
public void testForwardedProxyHeadersWithPathAndDynamicBackchannel(LaunchResult result) {
|
||||
assertFrontEndUrl("https://mykeycloak.org:8443", "https://mykeycloak.org:8443/path/");
|
||||
// a backend url generated via the frontend protocol/host/port should be a front-end url
|
||||
assertBackEndUrl("https://mykeycloak.org:8443", "https://mykeycloak.org:8443/path/");
|
||||
// any other protocol/host/port will be the backend
|
||||
assertBackEndUrl("http://localhost:8080", "http://localhost:8080/");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Launch({ "start-dev", "--hostname-strict=false", "--proxy-headers=xforwarded" })
|
||||
public void testXForwardedProxyHeaders() {
|
||||
@ -151,4 +161,10 @@ public class ProxyHostnameV2DistTest {
|
||||
Assert.assertEquals(expectedBaseUrl + "realms/master/protocol/openid-connect/auth", getServerMetadata(requestBaseUrl)
|
||||
.getAuthorizationEndpoint());
|
||||
}
|
||||
|
||||
private void assertBackEndUrl(String requestBaseUrl, String expectedBaseUrl) {
|
||||
Assert.assertEquals(expectedBaseUrl + "realms/master/protocol/openid-connect/token", getServerMetadata(requestBaseUrl)
|
||||
.getTokenEndpoint());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -67,7 +67,7 @@ public class HostnameV2Provider implements HostnameProvider {
|
||||
builder.host("localhost");
|
||||
break;
|
||||
case BACKEND:
|
||||
builder = backchannelDynamic ? originalUriInfo.getBaseUriBuilder() : getFrontUriBuilder(originalUriInfo);
|
||||
builder = backchannelDynamic && !isFrontendRequest(originalUriInfo) ? originalUriInfo.getBaseUriBuilder() : getFrontUriBuilder(originalUriInfo);
|
||||
break;
|
||||
case FRONTEND:
|
||||
builder = getFrontUriBuilder(originalUriInfo);
|
||||
@ -76,13 +76,29 @@ public class HostnameV2Provider implements HostnameProvider {
|
||||
throw new IllegalArgumentException("Unknown URL type");
|
||||
}
|
||||
|
||||
URI uri = builder.build();
|
||||
// sanitize ports
|
||||
URI uriPeak = builder.build();
|
||||
if ((uriPeak.getScheme().equals("http") && uriPeak.getPort() == 80) || (uriPeak.getScheme().equals("https") && uriPeak.getPort() == 443)) {
|
||||
builder.port(-1);
|
||||
int normalizedPort = normalizedPort(uri);
|
||||
if (normalizedPort != uri.getPort()) {
|
||||
builder.port(normalizedPort);
|
||||
uri = builder.build();
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
return uri;
|
||||
}
|
||||
|
||||
private int normalizedPort(URI uri) {
|
||||
if ((uri.getScheme().equals("http") && uri.getPort() == 80) || (uri.getScheme().equals("https") && uri.getPort() == 443)) {
|
||||
return -1;
|
||||
}
|
||||
return uri.getPort();
|
||||
}
|
||||
|
||||
private boolean isFrontendRequest(UriInfo originalUriInfo) {
|
||||
URI frontend = getFrontUriBuilder(originalUriInfo).build();
|
||||
return frontend.getScheme().equals(originalUriInfo.getBaseUri().getScheme()) &&
|
||||
frontend.getHost().equals(originalUriInfo.getBaseUri().getHost()) &&
|
||||
frontend.getPort() == normalizedPort(originalUriInfo.getBaseUri());
|
||||
}
|
||||
|
||||
private UriBuilder getFrontUriBuilder(UriInfo originalUriInfo) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user