diff --git a/components/abstractions/src/main/java/com/microsoft/kiota/authentication/AllowedHostsValidator.java b/components/abstractions/src/main/java/com/microsoft/kiota/authentication/AllowedHostsValidator.java index 866568f7..5da5529d 100644 --- a/components/abstractions/src/main/java/com/microsoft/kiota/authentication/AllowedHostsValidator.java +++ b/components/abstractions/src/main/java/com/microsoft/kiota/authentication/AllowedHostsValidator.java @@ -58,7 +58,18 @@ public void setAllowedHosts(@Nonnull final Set allowedHosts) { * @return true if the host is allowed, false otherwise. */ public boolean isUrlHostValid(@Nonnull final URI uri) { - return validHosts.isEmpty() - || validHosts.contains(uri.getHost().trim().toLowerCase(Locale.ROOT)); + if (validHosts.isEmpty()) { + return true; + } + final String host = uri.getHost().trim().toLowerCase(Locale.ROOT); + if (validHosts.contains(host)) { + return true; + } + for (final String validHost : validHosts) { + if (validHost.startsWith(".") && host.endsWith(validHost)) { + return true; + } + } + return false; } } diff --git a/components/abstractions/src/test/java/com/microsoft/kiota/authentication/AllowedHostValidatorTest.java b/components/abstractions/src/test/java/com/microsoft/kiota/authentication/AllowedHostValidatorTest.java index 5ac7b04b..6f1a54b0 100644 --- a/components/abstractions/src/test/java/com/microsoft/kiota/authentication/AllowedHostValidatorTest.java +++ b/components/abstractions/src/test/java/com/microsoft/kiota/authentication/AllowedHostValidatorTest.java @@ -1,6 +1,7 @@ package com.microsoft.kiota.authentication; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -8,6 +9,7 @@ import java.net.URI; import java.net.URISyntaxException; +import java.util.Collections; class AllowedHostValidatorTest { @@ -34,4 +36,61 @@ void initialisesAllowedHostsSuccessfully() throws URISyntaxException { assertTrue(validator.getAllowedHosts().contains("graph.microsoft.us")); assertTrue(validator.isUrlHostValid(new URI("https://graph.microsoft.com/v1/me"))); } + + @Test + void returnsFalseForSubdomainMatchingExactHost() throws URISyntaxException { + final AllowedHostsValidator validator = new AllowedHostsValidator("example.com"); + + assertFalse(validator.isUrlHostValid(new URI("https://sub.example.com/path"))); + } + + @Test + void returnsTrueForSubdomainMatchingAllowedSuffix() throws URISyntaxException { + final AllowedHostsValidator validator = new AllowedHostsValidator(".fabric.microsoft.com"); + + assertTrue( + validator.isUrlHostValid( + new URI("https://abc.123.graphql.fabric.microsoft.com/path"))); + } + + @Test + void returnsFalseForBareDomainWhenAllowedAsSuffix() throws URISyntaxException { + final AllowedHostsValidator validator = new AllowedHostsValidator(".fabric.microsoft.com"); + + assertFalse(validator.isUrlHostValid(new URI("https://fabric.microsoft.com/path"))); + } + + @Test + void suffixHostMatchingIsCaseInsensitive() throws URISyntaxException { + final AllowedHostsValidator validator = new AllowedHostsValidator(".Fabric.Microsoft.COM"); + + assertTrue( + validator.isUrlHostValid( + new URI("https://ABC.z2c.graphql.fabric.microsoft.com/path"))); + } + + @Test + void allowsMultipleValidHosts() throws URISyntaxException { + final AllowedHostsValidator validator = + new AllowedHostsValidator( + "example.com", "api.example.com", ".fabric.microsoft.com"); + + assertTrue(validator.isUrlHostValid(new URI("https://example.com/path"))); + assertTrue(validator.isUrlHostValid(new URI("https://api.example.com/path"))); + assertFalse(validator.isUrlHostValid(new URI("https://other.com/path"))); + assertTrue( + validator.isUrlHostValid( + new URI("https://abc.123.graphql.fabric.microsoft.com/path"))); + } + + @Test + void allowsSuffixBasedHostsAfterUpdate() throws URISyntaxException { + final AllowedHostsValidator validator = new AllowedHostsValidator("example.com"); + + validator.setAllowedHosts(Collections.singleton(".fabric.microsoft.com")); + + assertTrue( + validator.isUrlHostValid( + new URI("https://abc.123.graphql.fabric.microsoft.com/path"))); + } }