diff --git a/common/src/main/java/org/keycloak/common/enums/SslRequired.java b/common/src/main/java/org/keycloak/common/enums/SslRequired.java index 19d30ccf6a..4c5519db22 100644 --- a/common/src/main/java/org/keycloak/common/enums/SslRequired.java +++ b/common/src/main/java/org/keycloak/common/enums/SslRequired.java @@ -51,10 +51,23 @@ public enum SslRequired { private boolean isLocal(String remoteAddress) { try { InetAddress inetAddress = InetAddress.getByName(remoteAddress); - return inetAddress.isAnyLocalAddress() || inetAddress.isLoopbackAddress() || inetAddress.isSiteLocalAddress(); + return inetAddress.isAnyLocalAddress() || inetAddress.isLoopbackAddress() || inetAddress.isSiteLocalAddress() || inetAddress.isLinkLocalAddress() || isUniqueLocal(inetAddress); } catch (UnknownHostException e) { return false; } } + /** + * Check if the address is within IPv6 unique local address (ULA) range RFC4193. + */ + private boolean isUniqueLocal(InetAddress address) { + if (address instanceof java.net.Inet6Address) { + byte[] addr = address.getAddress(); + // Check if address is in unique local range fc00::/7 + return ((byte) (addr[0] & 0b11111110)) == (byte) 0xFC; + } + + return false; + } + } diff --git a/docs/documentation/server_admin/topics/realms/ssl.adoc b/docs/documentation/server_admin/topics/realms/ssl.adoc index 3ee8f95d7f..ee57e4bfb0 100644 --- a/docs/documentation/server_admin/topics/realms/ssl.adoc +++ b/docs/documentation/server_admin/topics/realms/ssl.adoc @@ -17,7 +17,7 @@ image:images/general-tab.png[General Tab] . Set *Require SSL* to one of the following SSL modes: * *External requests* - Users can interact with {project_name} without SSL so long as they stick to private IP addresses such as `localhost`, `127.0.0.1`, `10.x.x.x`, `192.168.x.x`, and `172.16.x.x`. + Users can interact with {project_name} without SSL so long as they stick to private IPv4 addresses such as `localhost`, `127.0.0.1`, `10.x.x.x`, `192.168.x.x`, `172.16.x.x` or IPv6 link-local and unique-local addresses. If you try to access {project_name} without SSL from a non-private IP address, you will get an error. * *None*