diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/DefaultRedirectStrategy.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/DefaultRedirectStrategy.java index 9b1b24adfd..ca0b41f64d 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/DefaultRedirectStrategy.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/DefaultRedirectStrategy.java @@ -93,7 +93,7 @@ public boolean isRedirectAllowed( final HttpRequest redirect, final HttpContext context) { - // If authority (host + effective port) differs, disallow automatic redirect + // If the origin (scheme, host and effective port) differs, disallow automatic redirect if (!isSameAuthority(currentTarget, newTarget)) { for (final Iterator
it = redirect.headerIterator(); it.hasNext(); ) { final Header header = it.next(); @@ -111,6 +111,9 @@ private boolean isSameAuthority(final HttpHost h1, final HttpHost h2) { if (h1 == null || h2 == null) { return false; } + if (!h1.getSchemeName().equalsIgnoreCase(h2.getSchemeName())) { + return false; + } final String host1 = h1.getHostName(); final String host2 = h2.getHostName(); if (!host1.equalsIgnoreCase(host2)) { diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/TestDefaultRedirectStrategy.java b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/TestDefaultRedirectStrategy.java index a874b42682..6617648b41 100644 --- a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/TestDefaultRedirectStrategy.java +++ b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/TestDefaultRedirectStrategy.java @@ -320,6 +320,48 @@ void testRedirectAllowed() throws Exception { + @Test + void testRedirectAllowedCrossSchemeSamePort() { + final DefaultRedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); + + // https -> http on the same host and same explicit port is a different origin, + // so a redirect carrying credential-bearing headers is not followed + final HttpHost secure = new HttpHost("https", "example.com", 8443); + final HttpHost insecure = new HttpHost("http", "example.com", 8443); + + Assertions.assertFalse(redirectStrategy.isRedirectAllowed( + secure, + insecure, + BasicRequestBuilder.get("/") + .addHeader(HttpHeaders.AUTHORIZATION, "let me pass") + .build(), + null)); + + Assertions.assertFalse(redirectStrategy.isRedirectAllowed( + secure, + insecure, + BasicRequestBuilder.get("/") + .addHeader(HttpHeaders.COOKIE, "stuff=blah") + .build(), + null)); + + // no sensitive headers -> the redirect itself is still permitted + Assertions.assertTrue(redirectStrategy.isRedirectAllowed( + secure, + insecure, + BasicRequestBuilder.get("/").build(), + null)); + + // same scheme, host and port stays same origin + Assertions.assertTrue(redirectStrategy.isRedirectAllowed( + secure, + new HttpHost("https", "example.com", 8443), + BasicRequestBuilder.get("/") + .addHeader(HttpHeaders.AUTHORIZATION, "let me pass") + .build(), + null)); + } + @Test void testRedirectAllowedDefaultPortNormalization() { final DefaultRedirectStrategy redirectStrategy = new DefaultRedirectStrategy();