From 29a470ed33d486efe6544d83e0b1952a6f72b99e Mon Sep 17 00:00:00 2001 From: ramsessanchez <63934382+ramsessanchez@users.noreply.github.com> Date: Thu, 12 Feb 2026 11:43:18 -0800 Subject: [PATCH 01/18] fix vulnerability where all headers are passed on redirect --- .../http/middleware/RedirectHandler.java | 5 ++- .../http/middleware/RedirectHandlerTests.java | 44 +++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java index 4cc2d4c9a..ff2a7862b 100644 --- a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java +++ b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java @@ -111,8 +111,11 @@ Request getRedirect(final Request request, final Response userResponse) boolean sameScheme = locationUrl.scheme().equalsIgnoreCase(requestUrl.scheme()); boolean sameHost = locationUrl.host().toString().equalsIgnoreCase(requestUrl.host().toString()); - if (!sameScheme || !sameHost) { + boolean samePort = locationUrl.port() == requestUrl.port(); + if (!sameScheme || !sameHost || !samePort) { requestBuilder.removeHeader("Authorization"); + requestBuilder.removeHeader("Cookie"); + requestBuilder.removeHeader("Proxy-Authorization"); } // Response status code 303 See Other then POST changes to GET diff --git a/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java b/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java index e72a3fafc..27e8cf8e8 100644 --- a/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java +++ b/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java @@ -1,6 +1,8 @@ package com.microsoft.kiota.http.middleware; +import static org.junit.Assert.assertNull; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import com.microsoft.kiota.http.KiotaClientFactory; import com.microsoft.kiota.http.middleware.options.RedirectHandlerOption; @@ -8,6 +10,7 @@ import okhttp3.*; import okhttp3.mockwebserver.MockResponse; import okhttp3.mockwebserver.MockWebServer; +import okhttp3.mockwebserver.RecordedRequest; import org.junit.jupiter.api.Test; @@ -54,4 +57,45 @@ void redirectsCanBeDisabled() throws Exception { assertEquals(301, response.code()); } + + @Test + void crossHostRedirectLeaksCookies() throws Exception { + Request original = new Request.Builder() + .url("http://trusted.example.com/api") + .addHeader("Authorization", "Bearer token") + .addHeader("Cookie", "session=SECRET") + .addHeader("Proxy-Authorization", "Basic cHJveHk6cGFzcw==") + .build(); + Response redirect = new Response.Builder() + .request(original).protocol(Protocol.HTTP_1_1) + .code(302).message("Found") + .header("Location", "http://evil.attacker.com/steal") + .body(ResponseBody.create("", MediaType.parse("text/plain"))) + .build(); + Request result = new RedirectHandler().getRedirect(original, redirect); + assertNotNull(result); + assertEquals("evil.attacker.com", result.url().host()); + assertNull(result.header("Authorization")); // stripped (good) + assertNull(result.header("Cookie")); // stripped (good) + assertNull(result.header("Proxy-Authorization")); // stripped (good) + } + + @Test + void endToEndProof() throws Exception { + var evil = new MockWebServer(); + evil.start(); + evil.enqueue(new MockResponse().setResponseCode(200)); + var trusted = new MockWebServer(); + trusted.start(); + trusted.enqueue(new MockResponse().setResponseCode(302) + .setHeader("Location", evil.url("/steal"))); + OkHttpClient client = KiotaClientFactory.create(new Interceptor[]{new RedirectHandler()}).build(); + client.newCall(new Request.Builder().url(trusted.url("/api")).addHeader("Cookie", "session=SECRET").build()).execute(); + trusted.takeRequest(); + RecordedRequest captured = evil.takeRequest(); + assertNull(captured.getHeader("Cookie")); + evil.shutdown(); + trusted.shutdown(); + } + } From 5364a519bcff22e235942495dba5187aae9a5be0 Mon Sep 17 00:00:00 2001 From: ramsessanchez <63934382+ramsessanchez@users.noreply.github.com> Date: Thu, 12 Feb 2026 14:12:16 -0800 Subject: [PATCH 02/18] formatting --- .../http/middleware/RedirectHandlerTests.java | 45 +++++++++++-------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java b/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java index 27e8cf8e8..a88628651 100644 --- a/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java +++ b/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java @@ -60,18 +60,22 @@ void redirectsCanBeDisabled() throws Exception { @Test void crossHostRedirectLeaksCookies() throws Exception { - Request original = new Request.Builder() - .url("http://trusted.example.com/api") - .addHeader("Authorization", "Bearer token") - .addHeader("Cookie", "session=SECRET") - .addHeader("Proxy-Authorization", "Basic cHJveHk6cGFzcw==") - .build(); - Response redirect = new Response.Builder() - .request(original).protocol(Protocol.HTTP_1_1) - .code(302).message("Found") - .header("Location", "http://evil.attacker.com/steal") - .body(ResponseBody.create("", MediaType.parse("text/plain"))) - .build(); + Request original = + new Request.Builder() + .url("http://trusted.example.com/api") + .addHeader("Authorization", "Bearer token") + .addHeader("Cookie", "session=SECRET") + .addHeader("Proxy-Authorization", "Basic cHJveHk6cGFzcw==") + .build(); + Response redirect = + new Response.Builder() + .request(original) + .protocol(Protocol.HTTP_1_1) + .code(302) + .message("Found") + .header("Location", "http://evil.attacker.com/steal") + .body(ResponseBody.create("", MediaType.parse("text/plain"))) + .build(); Request result = new RedirectHandler().getRedirect(original, redirect); assertNotNull(result); assertEquals("evil.attacker.com", result.url().host()); @@ -87,15 +91,20 @@ void endToEndProof() throws Exception { evil.enqueue(new MockResponse().setResponseCode(200)); var trusted = new MockWebServer(); trusted.start(); - trusted.enqueue(new MockResponse().setResponseCode(302) - .setHeader("Location", evil.url("/steal"))); - OkHttpClient client = KiotaClientFactory.create(new Interceptor[]{new RedirectHandler()}).build(); - client.newCall(new Request.Builder().url(trusted.url("/api")).addHeader("Cookie", "session=SECRET").build()).execute(); + trusted.enqueue( + new MockResponse().setResponseCode(302).setHeader("Location", evil.url("/steal"))); + OkHttpClient client = + KiotaClientFactory.create(new Interceptor[] {new RedirectHandler()}).build(); + client.newCall( + new Request.Builder() + .url(trusted.url("/api")) + .addHeader("Cookie", "session=SECRET") + .build()) + .execute(); trusted.takeRequest(); RecordedRequest captured = evil.takeRequest(); - assertNull(captured.getHeader("Cookie")); + assertNull(captured.getHeader("Cookie")); evil.shutdown(); trusted.shutdown(); } - } From 026aaceb108730de3a74db9ea357b0d5dc7e9d8a Mon Sep 17 00:00:00 2001 From: ramsessanchez <63934382+ramsessanchez@users.noreply.github.com> Date: Thu, 12 Feb 2026 14:15:40 -0800 Subject: [PATCH 03/18] remove test secret --- .../microsoft/kiota/http/middleware/RedirectHandlerTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java b/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java index a88628651..e07e533ed 100644 --- a/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java +++ b/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java @@ -65,7 +65,7 @@ void crossHostRedirectLeaksCookies() throws Exception { .url("http://trusted.example.com/api") .addHeader("Authorization", "Bearer token") .addHeader("Cookie", "session=SECRET") - .addHeader("Proxy-Authorization", "Basic cHJveHk6cGFzcw==") + .addHeader("Proxy-Authorization", "Basic ") .build(); Response redirect = new Response.Builder() From a4970d20104052b9b4b16b33abe968aa43eb2376 Mon Sep 17 00:00:00 2001 From: Adrian Date: Fri, 27 Feb 2026 13:47:26 -0600 Subject: [PATCH 04/18] updating redirect implementation --- .../http/middleware/RedirectHandler.java | 27 +-- .../options/RedirectHandlerOption.java | 112 ++++++++- .../http/middleware/RedirectHandlerTests.java | 222 +++++++++++++++++- 3 files changed, 343 insertions(+), 18 deletions(-) diff --git a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java index ff2a7862b..1d3636a52 100644 --- a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java +++ b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java @@ -81,7 +81,11 @@ boolean isRedirected( return false; } - Request getRedirect(final Request request, final Response userResponse) + Request getRedirect( + final Request request, + final Response userResponse, + final RedirectHandlerOption redirectOption, + final Chain chain) throws ProtocolException { String location = userResponse.header("Location"); if (location == null || location.length() == 0) return null; @@ -105,18 +109,12 @@ Request getRedirect(final Request request, final Response userResponse) // Most redirects don't include a request body. Request.Builder requestBuilder = userResponse.request().newBuilder(); - // When redirecting across hosts, drop all authentication headers. This - // is potentially annoying to the application layer since they have no - // way to retain them. - boolean sameScheme = locationUrl.scheme().equalsIgnoreCase(requestUrl.scheme()); - boolean sameHost = - locationUrl.host().toString().equalsIgnoreCase(requestUrl.host().toString()); - boolean samePort = locationUrl.port() == requestUrl.port(); - if (!sameScheme || !sameHost || !samePort) { - requestBuilder.removeHeader("Authorization"); - requestBuilder.removeHeader("Cookie"); - requestBuilder.removeHeader("Proxy-Authorization"); - } + // Scrub sensitive headers before following the redirect + java.util.function.Function proxyResolver = + RedirectHandlerOption.getProxyResolver( + chain.call().client().proxySelector()); + redirectOption.scrubSensitiveHeaders().scrubHeaders( + requestBuilder, requestUrl, locationUrl, proxyResolver); // Response status code 303 See Other then POST changes to GET if (userResponse.code() == HTTP_SEE_OTHER) { @@ -166,7 +164,8 @@ Request getRedirect(final Request request, final Response userResponse) isRedirected(request, response, requestsCount, redirectOption) && redirectOption.shouldRedirect().shouldRedirect(response); - final Request followup = shouldRedirect ? getRedirect(request, response) : null; + final Request followup = + shouldRedirect ? getRedirect(request, response, redirectOption, chain) : null; if (followup != null) { response.close(); request = followup; diff --git a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/options/RedirectHandlerOption.java b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/options/RedirectHandlerOption.java index e3b18d306..6cafde42c 100644 --- a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/options/RedirectHandlerOption.java +++ b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/options/RedirectHandlerOption.java @@ -5,6 +5,17 @@ import jakarta.annotation.Nonnull; import jakarta.annotation.Nullable; +import okhttp3.HttpUrl; +import okhttp3.Request; + +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.ProxySelector; +import java.net.URI; +import java.util.List; +import java.util.Objects; +import java.util.function.Function; + /** * Options to be passed to the redirect middleware. */ @@ -28,11 +39,59 @@ public class RedirectHandlerOption implements RequestOption { */ @Nonnull public static final IShouldRedirect DEFAULT_SHOULD_REDIRECT = response -> true; + @Nonnull private final IScrubSensitiveHeaders scrubSensitiveHeaders; + + /** + * Functional interface for scrubbing sensitive headers during redirects. + */ + @FunctionalInterface + public interface IScrubSensitiveHeaders { + /** + * Scrubs sensitive headers from the request before following a redirect. + * @param requestBuilder The request builder to modify + * @param originalUrl The original request URL + * @param newUrl The new redirect URL + * @param proxyResolver A function that returns the proxy for a given destination, or null if no proxy applies + */ + void scrubHeaders( + @Nonnull Request.Builder requestBuilder, + @Nonnull HttpUrl originalUrl, + @Nonnull HttpUrl newUrl, + @Nullable Function proxyResolver); + } + + /** + * The default implementation for scrubbing sensitive headers during redirects. + * This method removes Authorization and Cookie headers when the host or scheme changes, + * and removes Proxy-Authorization headers when no proxy is configured or the proxy is bypassed for the new URL. + */ + @Nonnull public static final IScrubSensitiveHeaders DEFAULT_SCRUB_SENSITIVE_HEADERS = + (requestBuilder, originalUrl, newUrl, proxyResolver) -> { + Objects.requireNonNull(requestBuilder, "parameter requestBuilder cannot be null"); + Objects.requireNonNull(originalUrl, "parameter originalUrl cannot be null"); + Objects.requireNonNull(newUrl, "parameter newUrl cannot be null"); + + // Remove Authorization and Cookie headers if the request's scheme or host changes + boolean isDifferentHostOrScheme = + !newUrl.host().equalsIgnoreCase(originalUrl.host()) + || !newUrl.scheme().equalsIgnoreCase(originalUrl.scheme()); + if (isDifferentHostOrScheme) { + requestBuilder.removeHeader("Authorization"); + requestBuilder.removeHeader("Cookie"); + } + + // Remove Proxy-Authorization if no proxy is configured or the URL is bypassed + boolean isProxyInactive = proxyResolver == null || proxyResolver.apply(newUrl) == null; + if (isProxyInactive) { + requestBuilder.removeHeader("Proxy-Authorization"); + } + }; + /** * Create default instance of redirect options, with default values of max redirects and should redirect */ public RedirectHandlerOption() { - this(DEFAULT_MAX_REDIRECTS, DEFAULT_SHOULD_REDIRECT); + this(DEFAULT_MAX_REDIRECTS, DEFAULT_SHOULD_REDIRECT, DEFAULT_SCRUB_SENSITIVE_HEADERS); } /** @@ -41,6 +100,19 @@ public RedirectHandlerOption() { * @param shouldRedirect Should redirect callback called before every redirect */ public RedirectHandlerOption(int maxRedirects, @Nullable final IShouldRedirect shouldRedirect) { + this(maxRedirects, shouldRedirect, DEFAULT_SCRUB_SENSITIVE_HEADERS); + } + + /** + * Create an instance with provided values + * @param maxRedirects Max redirects to occur + * @param shouldRedirect Should redirect callback called before every redirect + * @param scrubSensitiveHeaders Callback to scrub sensitive headers during redirects + */ + public RedirectHandlerOption( + int maxRedirects, + @Nullable final IShouldRedirect shouldRedirect, + @Nullable final IScrubSensitiveHeaders scrubSensitiveHeaders) { if (maxRedirects < 0) throw new IllegalArgumentException("Max redirects cannot be negative"); if (maxRedirects > MAX_REDIRECTS) @@ -48,6 +120,10 @@ public RedirectHandlerOption(int maxRedirects, @Nullable final IShouldRedirect s this.maxRedirects = maxRedirects; this.shouldRedirect = shouldRedirect != null ? shouldRedirect : DEFAULT_SHOULD_REDIRECT; + this.scrubSensitiveHeaders = + scrubSensitiveHeaders != null + ? scrubSensitiveHeaders + : DEFAULT_SCRUB_SENSITIVE_HEADERS; } /** @@ -66,6 +142,40 @@ public int maxRedirects() { return this.shouldRedirect; } + /** + * Gets the callback for scrubbing sensitive headers during redirects. + * @return scrub sensitive headers callback + */ + @Nonnull public IScrubSensitiveHeaders scrubSensitiveHeaders() { + return this.scrubSensitiveHeaders; + } + + /** + * Helper method to get a proxy resolver from a ProxySelector. + * @param proxySelector The ProxySelector to use, or null if no proxy is configured + * @return A function that resolves proxies for a given HttpUrl, or null if no proxy selector is provided + */ + @Nullable public static Function getProxyResolver( + @Nullable final ProxySelector proxySelector) { + if (proxySelector == null) { + return null; + } + return url -> { + try { + URI uri = new URI(url.scheme(), null, url.host(), url.port(), null, null, null); + List proxies = proxySelector.select(uri); + if (proxies != null && !proxies.isEmpty()) { + Proxy proxy = proxies.get(0); + // Return null for DIRECT proxies (no proxy) + return proxy.type() == Proxy.Type.DIRECT ? null : proxy; + } + return null; + } catch (Exception e) { + return null; + } + }; + } + /** {@inheritDoc} */ @SuppressWarnings("unchecked") @Override diff --git a/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java b/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java index e07e533ed..164457da8 100644 --- a/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java +++ b/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java @@ -3,6 +3,7 @@ import static org.junit.Assert.assertNull; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.Mockito.*; import com.microsoft.kiota.http.KiotaClientFactory; import com.microsoft.kiota.http.middleware.options.RedirectHandlerOption; @@ -14,6 +15,10 @@ import org.junit.jupiter.api.Test; +import java.io.IOException; +import java.net.*; +import java.util.Collections; + @SuppressWarnings("resource") public class RedirectHandlerTests { @@ -59,7 +64,7 @@ void redirectsCanBeDisabled() throws Exception { } @Test - void crossHostRedirectLeaksCookies() throws Exception { + void crossHostRedirectStripsAuthHeaders() throws Exception { Request original = new Request.Builder() .url("http://trusted.example.com/api") @@ -76,12 +81,21 @@ void crossHostRedirectLeaksCookies() throws Exception { .header("Location", "http://evil.attacker.com/steal") .body(ResponseBody.create("", MediaType.parse("text/plain"))) .build(); - Request result = new RedirectHandler().getRedirect(original, redirect); + + // Mock chain to get client without proxy + Interceptor.Chain chain = mock(Interceptor.Chain.class); + Call call = mock(Call.class); + OkHttpClient client = new OkHttpClient.Builder().build(); + when(chain.call()).thenReturn(call); + when(call.client()).thenReturn(client); + + RedirectHandlerOption option = new RedirectHandlerOption(); + Request result = new RedirectHandler().getRedirect(original, redirect, option, chain); assertNotNull(result); assertEquals("evil.attacker.com", result.url().host()); assertNull(result.header("Authorization")); // stripped (good) assertNull(result.header("Cookie")); // stripped (good) - assertNull(result.header("Proxy-Authorization")); // stripped (good) + assertNull(result.header("Proxy-Authorization")); // stripped because no proxy (good) } @Test @@ -107,4 +121,206 @@ void endToEndProof() throws Exception { evil.shutdown(); trusted.shutdown(); } + + @Test + void sameHostRedirectKeepsAllHeaders() throws Exception { + Request original = + new Request.Builder() + .url("http://trusted.example.com/api") + .addHeader("Authorization", "Bearer token") + .addHeader("Cookie", "session=SECRET") + .addHeader("Proxy-Authorization", "Basic ") + .build(); + Response redirect = + new Response.Builder() + .request(original) + .protocol(Protocol.HTTP_1_1) + .code(302) + .message("Found") + .header("Location", "http://trusted.example.com/other") + .body(ResponseBody.create("", MediaType.parse("text/plain"))) + .build(); + + // Mock chain with proxy + Interceptor.Chain chain = mock(Interceptor.Chain.class); + Call call = mock(Call.class); + ProxySelector proxySelector = mock(ProxySelector.class); + Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy.example.com", 8080)); + when(proxySelector.select(any(URI.class))).thenReturn(Collections.singletonList(proxy)); + + OkHttpClient client = new OkHttpClient.Builder().proxySelector(proxySelector).build(); + when(chain.call()).thenReturn(call); + when(call.client()).thenReturn(client); + + RedirectHandlerOption option = new RedirectHandlerOption(); + Request result = new RedirectHandler().getRedirect(original, redirect, option, chain); + + assertNotNull(result); + assertEquals("trusted.example.com", result.url().host()); + assertNotNull(result.header("Authorization")); // kept (same host) + assertNotNull(result.header("Cookie")); // kept (same host) + assertNotNull(result.header("Proxy-Authorization")); // kept (proxy is active) + } + + @Test + void crossHostRedirectWithProxyKeepsProxyAuth() throws Exception { + Request original = + new Request.Builder() + .url("http://trusted.example.com/api") + .addHeader("Authorization", "Bearer token") + .addHeader("Cookie", "session=SECRET") + .addHeader("Proxy-Authorization", "Basic ") + .build(); + Response redirect = + new Response.Builder() + .request(original) + .protocol(Protocol.HTTP_1_1) + .code(302) + .message("Found") + .header("Location", "http://other.example.com/api") + .body(ResponseBody.create("", MediaType.parse("text/plain"))) + .build(); + + // Mock chain with active proxy + Interceptor.Chain chain = mock(Interceptor.Chain.class); + Call call = mock(Call.class); + ProxySelector proxySelector = mock(ProxySelector.class); + Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy.example.com", 8080)); + when(proxySelector.select(any(URI.class))).thenReturn(Collections.singletonList(proxy)); + + OkHttpClient client = new OkHttpClient.Builder().proxySelector(proxySelector).build(); + when(chain.call()).thenReturn(call); + when(call.client()).thenReturn(client); + + RedirectHandlerOption option = new RedirectHandlerOption(); + Request result = new RedirectHandler().getRedirect(original, redirect, option, chain); + + assertNotNull(result); + assertEquals("other.example.com", result.url().host()); + assertNull(result.header("Authorization")); // stripped (different host) + assertNull(result.header("Cookie")); // stripped (different host) + assertNotNull( + result.header("Proxy-Authorization")); // KEPT because proxy is still active (good) + } + + @Test + void crossHostRedirectWithDirectProxyStripsProxyAuth() throws Exception { + Request original = + new Request.Builder() + .url("http://trusted.example.com/api") + .addHeader("Authorization", "Bearer token") + .addHeader("Cookie", "session=SECRET") + .addHeader("Proxy-Authorization", "Basic ") + .build(); + Response redirect = + new Response.Builder() + .request(original) + .protocol(Protocol.HTTP_1_1) + .code(302) + .message("Found") + .header("Location", "http://other.example.com/api") + .body(ResponseBody.create("", MediaType.parse("text/plain"))) + .build(); + + // Mock chain with DIRECT proxy (no proxy) + Interceptor.Chain chain = mock(Interceptor.Chain.class); + Call call = mock(Call.class); + ProxySelector proxySelector = mock(ProxySelector.class); + when(proxySelector.select(any(URI.class))) + .thenReturn(Collections.singletonList(Proxy.NO_PROXY)); + + OkHttpClient client = new OkHttpClient.Builder().proxySelector(proxySelector).build(); + when(chain.call()).thenReturn(call); + when(call.client()).thenReturn(client); + + RedirectHandlerOption option = new RedirectHandlerOption(); + Request result = new RedirectHandler().getRedirect(original, redirect, option, chain); + + assertNotNull(result); + assertEquals("other.example.com", result.url().host()); + assertNull(result.header("Authorization")); // stripped (different host) + assertNull(result.header("Cookie")); // stripped (different host) + assertNull( + result.header( + "Proxy-Authorization")); // stripped because proxy is DIRECT/inactive (good) + } + + @Test + void schemeChangeStripsAuthHeaders() throws Exception { + Request original = + new Request.Builder() + .url("https://trusted.example.com/api") + .addHeader("Authorization", "Bearer token") + .addHeader("Cookie", "session=SECRET") + .addHeader("Proxy-Authorization", "Basic ") + .build(); + Response redirect = + new Response.Builder() + .request(original) + .protocol(Protocol.HTTP_1_1) + .code(302) + .message("Found") + .header( + "Location", + "http://trusted.example.com/other") // HTTPS -> HTTP (same host) + .body(ResponseBody.create("", MediaType.parse("text/plain"))) + .build(); + + // Mock chain without proxy + Interceptor.Chain chain = mock(Interceptor.Chain.class); + Call call = mock(Call.class); + OkHttpClient client = new OkHttpClient.Builder().build(); + when(chain.call()).thenReturn(call); + when(call.client()).thenReturn(client); + + RedirectHandlerOption option = new RedirectHandlerOption(); + Request result = new RedirectHandler().getRedirect(original, redirect, option, chain); + + assertNotNull(result); + assertEquals("trusted.example.com", result.url().host()); + assertEquals("http", result.url().scheme()); + assertNull(result.header("Authorization")); // stripped (scheme changed) + assertNull(result.header("Cookie")); // stripped (scheme changed) + assertNull(result.header("Proxy-Authorization")); // stripped (no proxy) + } + + @Test + void customScrubberIsUsed() throws Exception { + Request original = + new Request.Builder() + .url("http://trusted.example.com/api") + .addHeader("Authorization", "Bearer token") + .addHeader("Cookie", "session=SECRET") + .build(); + Response redirect = + new Response.Builder() + .request(original) + .protocol(Protocol.HTTP_1_1) + .code(302) + .message("Found") + .header("Location", "http://other.example.com/api") + .body(ResponseBody.create("", MediaType.parse("text/plain"))) + .build(); + + // Custom scrubber that never removes headers + RedirectHandlerOption.IScrubSensitiveHeaders customScrubber = + (requestBuilder, originalUrl, newUrl, proxyResolver) -> { + // Don't remove any headers + }; + + // Mock chain + Interceptor.Chain chain = mock(Interceptor.Chain.class); + Call call = mock(Call.class); + OkHttpClient client = new OkHttpClient.Builder().build(); + when(chain.call()).thenReturn(call); + when(call.client()).thenReturn(client); + + RedirectHandlerOption option = new RedirectHandlerOption(5, null, customScrubber); + Request result = new RedirectHandler().getRedirect(original, redirect, option, chain); + + assertNotNull(result); + assertEquals("other.example.com", result.url().host()); + assertNotNull(result.header("Authorization")); // KEPT by custom scrubber + assertNotNull(result.header("Cookie")); // KEPT by custom scrubber + } } From aec24147e46f46456c8a87b7e5c67ac917a35848 Mon Sep 17 00:00:00 2001 From: Adrian Date: Fri, 27 Feb 2026 14:24:54 -0600 Subject: [PATCH 05/18] Testing changes --- .../http/middleware/RedirectHandler.java | 18 ++++++++-- .../http/middleware/RedirectHandlerTests.java | 33 ++----------------- 2 files changed, 18 insertions(+), 33 deletions(-) diff --git a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java index 1d3636a52..394e84778 100644 --- a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java +++ b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java @@ -29,12 +29,13 @@ */ public class RedirectHandler implements Interceptor { @Nonnull private final RedirectHandlerOption mRedirectOption; + @Nullable private final java.net.ProxySelector mProxySelector; /** * Initialize using default redirect options, default IShouldRedirect and max redirect value */ public RedirectHandler() { - this(null); + this(null, null); } /** @@ -42,11 +43,23 @@ public RedirectHandler() { * @param redirectOption pass instance of redirect options to be used */ public RedirectHandler(@Nullable final RedirectHandlerOption redirectOption) { + this(redirectOption, null); + } + + /** + * Initialize using custom redirect options and proxy selector. + * @param redirectOption pass instance of redirect options to be used + * @param proxySelector The ProxySelector to use for determining proxy configuration, or null to use the system default + */ + public RedirectHandler( + @Nullable final RedirectHandlerOption redirectOption, + @Nullable final java.net.ProxySelector proxySelector) { if (redirectOption == null) { this.mRedirectOption = new RedirectHandlerOption(); } else { this.mRedirectOption = redirectOption; } + this.mProxySelector = proxySelector != null ? proxySelector : java.net.ProxySelector.getDefault(); } boolean isRedirected( @@ -111,8 +124,7 @@ Request getRedirect( // Scrub sensitive headers before following the redirect java.util.function.Function proxyResolver = - RedirectHandlerOption.getProxyResolver( - chain.call().client().proxySelector()); + RedirectHandlerOption.getProxyResolver(mProxySelector); redirectOption.scrubSensitiveHeaders().scrubHeaders( requestBuilder, requestUrl, locationUrl, proxyResolver); diff --git a/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java b/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java index 164457da8..c7d61f494 100644 --- a/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java +++ b/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java @@ -84,10 +84,6 @@ void crossHostRedirectStripsAuthHeaders() throws Exception { // Mock chain to get client without proxy Interceptor.Chain chain = mock(Interceptor.Chain.class); - Call call = mock(Call.class); - OkHttpClient client = new OkHttpClient.Builder().build(); - when(chain.call()).thenReturn(call); - when(call.client()).thenReturn(client); RedirectHandlerOption option = new RedirectHandlerOption(); Request result = new RedirectHandler().getRedirect(original, redirect, option, chain); @@ -143,17 +139,12 @@ void sameHostRedirectKeepsAllHeaders() throws Exception { // Mock chain with proxy Interceptor.Chain chain = mock(Interceptor.Chain.class); - Call call = mock(Call.class); ProxySelector proxySelector = mock(ProxySelector.class); Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy.example.com", 8080)); when(proxySelector.select(any(URI.class))).thenReturn(Collections.singletonList(proxy)); - OkHttpClient client = new OkHttpClient.Builder().proxySelector(proxySelector).build(); - when(chain.call()).thenReturn(call); - when(call.client()).thenReturn(client); - RedirectHandlerOption option = new RedirectHandlerOption(); - Request result = new RedirectHandler().getRedirect(original, redirect, option, chain); + Request result = new RedirectHandler(option, proxySelector).getRedirect(original, redirect, option, chain); assertNotNull(result); assertEquals("trusted.example.com", result.url().host()); @@ -183,17 +174,12 @@ void crossHostRedirectWithProxyKeepsProxyAuth() throws Exception { // Mock chain with active proxy Interceptor.Chain chain = mock(Interceptor.Chain.class); - Call call = mock(Call.class); ProxySelector proxySelector = mock(ProxySelector.class); Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy.example.com", 8080)); when(proxySelector.select(any(URI.class))).thenReturn(Collections.singletonList(proxy)); - OkHttpClient client = new OkHttpClient.Builder().proxySelector(proxySelector).build(); - when(chain.call()).thenReturn(call); - when(call.client()).thenReturn(client); - RedirectHandlerOption option = new RedirectHandlerOption(); - Request result = new RedirectHandler().getRedirect(original, redirect, option, chain); + Request result = new RedirectHandler(option, proxySelector).getRedirect(original, redirect, option, chain); assertNotNull(result); assertEquals("other.example.com", result.url().host()); @@ -224,17 +210,12 @@ void crossHostRedirectWithDirectProxyStripsProxyAuth() throws Exception { // Mock chain with DIRECT proxy (no proxy) Interceptor.Chain chain = mock(Interceptor.Chain.class); - Call call = mock(Call.class); ProxySelector proxySelector = mock(ProxySelector.class); when(proxySelector.select(any(URI.class))) .thenReturn(Collections.singletonList(Proxy.NO_PROXY)); - OkHttpClient client = new OkHttpClient.Builder().proxySelector(proxySelector).build(); - when(chain.call()).thenReturn(call); - when(call.client()).thenReturn(client); - RedirectHandlerOption option = new RedirectHandlerOption(); - Request result = new RedirectHandler().getRedirect(original, redirect, option, chain); + Request result = new RedirectHandler(option, proxySelector).getRedirect(original, redirect, option, chain); assertNotNull(result); assertEquals("other.example.com", result.url().host()); @@ -268,10 +249,6 @@ void schemeChangeStripsAuthHeaders() throws Exception { // Mock chain without proxy Interceptor.Chain chain = mock(Interceptor.Chain.class); - Call call = mock(Call.class); - OkHttpClient client = new OkHttpClient.Builder().build(); - when(chain.call()).thenReturn(call); - when(call.client()).thenReturn(client); RedirectHandlerOption option = new RedirectHandlerOption(); Request result = new RedirectHandler().getRedirect(original, redirect, option, chain); @@ -310,10 +287,6 @@ void customScrubberIsUsed() throws Exception { // Mock chain Interceptor.Chain chain = mock(Interceptor.Chain.class); - Call call = mock(Call.class); - OkHttpClient client = new OkHttpClient.Builder().build(); - when(chain.call()).thenReturn(call); - when(call.client()).thenReturn(client); RedirectHandlerOption option = new RedirectHandlerOption(5, null, customScrubber); Request result = new RedirectHandler().getRedirect(original, redirect, option, chain); From 437340c530b344095417850146f57061b7e8d945 Mon Sep 17 00:00:00 2001 From: Adrian Date: Fri, 27 Feb 2026 14:35:14 -0600 Subject: [PATCH 06/18] fixing linting issues --- .../kiota/http/middleware/RedirectHandler.java | 12 ++++++++---- .../middleware/options/RedirectHandlerOption.java | 4 ++-- .../kiota/http/middleware/RedirectHandlerTests.java | 12 +++++++++--- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java index 394e84778..9daf896b5 100644 --- a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java +++ b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java @@ -59,7 +59,8 @@ public RedirectHandler( } else { this.mRedirectOption = redirectOption; } - this.mProxySelector = proxySelector != null ? proxySelector : java.net.ProxySelector.getDefault(); + this.mProxySelector = + proxySelector != null ? proxySelector : java.net.ProxySelector.getDefault(); } boolean isRedirected( @@ -125,8 +126,9 @@ Request getRedirect( // Scrub sensitive headers before following the redirect java.util.function.Function proxyResolver = RedirectHandlerOption.getProxyResolver(mProxySelector); - redirectOption.scrubSensitiveHeaders().scrubHeaders( - requestBuilder, requestUrl, locationUrl, proxyResolver); + redirectOption + .scrubSensitiveHeaders() + .scrubHeaders(requestBuilder, requestUrl, locationUrl, proxyResolver); // Response status code 303 See Other then POST changes to GET if (userResponse.code() == HTTP_SEE_OTHER) { @@ -177,7 +179,9 @@ Request getRedirect( && redirectOption.shouldRedirect().shouldRedirect(response); final Request followup = - shouldRedirect ? getRedirect(request, response, redirectOption, chain) : null; + shouldRedirect + ? getRedirect(request, response, redirectOption, chain) + : null; if (followup != null) { response.close(); request = followup; diff --git a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/options/RedirectHandlerOption.java b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/options/RedirectHandlerOption.java index 6cafde42c..dd6e56f2a 100644 --- a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/options/RedirectHandlerOption.java +++ b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/options/RedirectHandlerOption.java @@ -8,7 +8,6 @@ import okhttp3.HttpUrl; import okhttp3.Request; -import java.net.InetSocketAddress; import java.net.Proxy; import java.net.ProxySelector; import java.net.URI; @@ -81,7 +80,8 @@ void scrubHeaders( } // Remove Proxy-Authorization if no proxy is configured or the URL is bypassed - boolean isProxyInactive = proxyResolver == null || proxyResolver.apply(newUrl) == null; + boolean isProxyInactive = + proxyResolver == null || proxyResolver.apply(newUrl) == null; if (isProxyInactive) { requestBuilder.removeHeader("Proxy-Authorization"); } diff --git a/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java b/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java index c7d61f494..7354b2099 100644 --- a/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java +++ b/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java @@ -144,7 +144,9 @@ void sameHostRedirectKeepsAllHeaders() throws Exception { when(proxySelector.select(any(URI.class))).thenReturn(Collections.singletonList(proxy)); RedirectHandlerOption option = new RedirectHandlerOption(); - Request result = new RedirectHandler(option, proxySelector).getRedirect(original, redirect, option, chain); + Request result = + new RedirectHandler(option, proxySelector) + .getRedirect(original, redirect, option, chain); assertNotNull(result); assertEquals("trusted.example.com", result.url().host()); @@ -179,7 +181,9 @@ void crossHostRedirectWithProxyKeepsProxyAuth() throws Exception { when(proxySelector.select(any(URI.class))).thenReturn(Collections.singletonList(proxy)); RedirectHandlerOption option = new RedirectHandlerOption(); - Request result = new RedirectHandler(option, proxySelector).getRedirect(original, redirect, option, chain); + Request result = + new RedirectHandler(option, proxySelector) + .getRedirect(original, redirect, option, chain); assertNotNull(result); assertEquals("other.example.com", result.url().host()); @@ -215,7 +219,9 @@ void crossHostRedirectWithDirectProxyStripsProxyAuth() throws Exception { .thenReturn(Collections.singletonList(Proxy.NO_PROXY)); RedirectHandlerOption option = new RedirectHandlerOption(); - Request result = new RedirectHandler(option, proxySelector).getRedirect(original, redirect, option, chain); + Request result = + new RedirectHandler(option, proxySelector) + .getRedirect(original, redirect, option, chain); assertNotNull(result); assertEquals("other.example.com", result.url().host()); From 37c5a4188f0d2cdc6285682832a99335a4aab5b8 Mon Sep 17 00:00:00 2001 From: Adrian Date: Fri, 27 Feb 2026 14:39:39 -0600 Subject: [PATCH 07/18] format issues fix --- .../microsoft/kiota/http/middleware/RedirectHandlerTests.java | 1 - 1 file changed, 1 deletion(-) diff --git a/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java b/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java index 7354b2099..9a32f8573 100644 --- a/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java +++ b/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java @@ -15,7 +15,6 @@ import org.junit.jupiter.api.Test; -import java.io.IOException; import java.net.*; import java.util.Collections; From cf142ea1743c1419fa11dfbe55f5d4fe7a02fa1a Mon Sep 17 00:00:00 2001 From: Adrian Date: Fri, 27 Feb 2026 15:01:03 -0600 Subject: [PATCH 08/18] fixing test --- .../com/microsoft/kiota/http/middleware/RedirectHandler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java index 9daf896b5..e482d06ef 100644 --- a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java +++ b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java @@ -113,9 +113,9 @@ Request getRedirect( location = request.url() + location; } - HttpUrl requestUrl = userResponse.request().url(); + HttpUrl requestUrl = request.url(); - HttpUrl locationUrl = userResponse.request().url().resolve(location); + HttpUrl locationUrl = request.url().resolve(location); // Don't follow redirects to unsupported protocols. if (locationUrl == null) return null; From 5746c345691d550ee2373c1f217aad37f1bb6c38 Mon Sep 17 00:00:00 2001 From: "Michael Mainer (from Dev Box)" <8527305+MIchaelMainer@users.noreply.github.com> Date: Fri, 27 Feb 2026 14:10:55 -0800 Subject: [PATCH 09/18] fix: check for port changes on redirect --- .../kiota/http/middleware/options/RedirectHandlerOption.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/options/RedirectHandlerOption.java b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/options/RedirectHandlerOption.java index dd6e56f2a..fb54e4860 100644 --- a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/options/RedirectHandlerOption.java +++ b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/options/RedirectHandlerOption.java @@ -70,10 +70,11 @@ void scrubHeaders( Objects.requireNonNull(originalUrl, "parameter originalUrl cannot be null"); Objects.requireNonNull(newUrl, "parameter newUrl cannot be null"); - // Remove Authorization and Cookie headers if the request's scheme or host changes + // Remove Authorization and Cookie headers if the request's scheme, host, or port changes boolean isDifferentHostOrScheme = !newUrl.host().equalsIgnoreCase(originalUrl.host()) - || !newUrl.scheme().equalsIgnoreCase(originalUrl.scheme()); + || !newUrl.scheme().equalsIgnoreCase(originalUrl.scheme()) + || newUrl.port() != originalUrl.port(); if (isDifferentHostOrScheme) { requestBuilder.removeHeader("Authorization"); requestBuilder.removeHeader("Cookie"); From c855923afced2eaa288d6578c63ca035e8da412b Mon Sep 17 00:00:00 2001 From: "Michael Mainer (from Dev Box)" <8527305+MIchaelMainer@users.noreply.github.com> Date: Fri, 27 Feb 2026 14:15:32 -0800 Subject: [PATCH 10/18] chore: fix formatting --- .../kiota/http/middleware/options/RedirectHandlerOption.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/options/RedirectHandlerOption.java b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/options/RedirectHandlerOption.java index fb54e4860..44305f492 100644 --- a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/options/RedirectHandlerOption.java +++ b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/options/RedirectHandlerOption.java @@ -70,7 +70,8 @@ void scrubHeaders( Objects.requireNonNull(originalUrl, "parameter originalUrl cannot be null"); Objects.requireNonNull(newUrl, "parameter newUrl cannot be null"); - // Remove Authorization and Cookie headers if the request's scheme, host, or port changes + // Remove Authorization and Cookie headers if the request's scheme, host, or port + // changes boolean isDifferentHostOrScheme = !newUrl.host().equalsIgnoreCase(originalUrl.host()) || !newUrl.scheme().equalsIgnoreCase(originalUrl.scheme()) From 7a44f88e83a41e801d02438041f1ec2718f404aa Mon Sep 17 00:00:00 2001 From: "Michael Mainer (from Dev Box)" <8527305+MIchaelMainer@users.noreply.github.com> Date: Fri, 27 Feb 2026 14:55:48 -0800 Subject: [PATCH 11/18] test: validate that custom headers are removed on redirect --- .../http/middleware/RedirectHandlerTests.java | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java b/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java index 9a32f8573..b0cce113d 100644 --- a/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java +++ b/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java @@ -301,4 +301,48 @@ void customScrubberIsUsed() throws Exception { assertNotNull(result.header("Authorization")); // KEPT by custom scrubber assertNotNull(result.header("Cookie")); // KEPT by custom scrubber } + + @Test + void customScrubberRemovesCustomHeaders() throws Exception { + Request original = + new Request.Builder() + .url("http://trusted.example.com/api") + .addHeader("Authorization", "Bearer token") + .addHeader("X-Custom-Secret", "my-secret-value") + .addHeader("X-Api-Key", "key-12345") + .addHeader("X-Safe-Header", "keep-me") + .build(); + Response redirect = + new Response.Builder() + .request(original) + .protocol(Protocol.HTTP_1_1) + .code(302) + .message("Found") + .header("Location", "http://other.example.com/api") + .body(ResponseBody.create("", MediaType.parse("text/plain"))) + .build(); + + // Custom scrubber that removes custom headers in addition to the defaults + RedirectHandlerOption.IScrubSensitiveHeaders customScrubber = + (requestBuilder, originalUrl, newUrl, proxyResolver) -> { + // Apply default scrubbing first + RedirectHandlerOption.DEFAULT_SCRUB_SENSITIVE_HEADERS.scrubHeaders( + requestBuilder, originalUrl, newUrl, proxyResolver); + // Also remove application-specific sensitive headers + requestBuilder.removeHeader("X-Custom-Secret"); + requestBuilder.removeHeader("X-Api-Key"); + }; + + Interceptor.Chain chain = mock(Interceptor.Chain.class); + + RedirectHandlerOption option = new RedirectHandlerOption(5, null, customScrubber); + Request result = new RedirectHandler().getRedirect(original, redirect, option, chain); + + assertNotNull(result); + assertEquals("other.example.com", result.url().host()); + assertNull(result.header("Authorization")); // stripped by default scrubber + assertNull(result.header("X-Custom-Secret")); // stripped by custom scrubber + assertNull(result.header("X-Api-Key")); // stripped by custom scrubber + assertNotNull(result.header("X-Safe-Header")); // kept (not in scrub list) + } } From 83e7b4841cc21fba33a81c2783043456a8fec0f5 Mon Sep 17 00:00:00 2001 From: Adrian Date: Mon, 2 Mar 2026 10:40:27 -0600 Subject: [PATCH 12/18] adding port condition --- .../http/middleware/RedirectHandler.java | 6 +- .../options/RedirectHandlerOption.java | 20 +++--- .../http/middleware/RedirectHandlerTests.java | 64 ++++++++++++++++++- 3 files changed, 77 insertions(+), 13 deletions(-) diff --git a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java index e482d06ef..f5d9f2c20 100644 --- a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java +++ b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java @@ -121,21 +121,21 @@ Request getRedirect( if (locationUrl == null) return null; // Most redirects don't include a request body. - Request.Builder requestBuilder = userResponse.request().newBuilder(); + Request.Builder requestBuilder = userResponse.request().newBuilder().url(locationUrl); // Scrub sensitive headers before following the redirect java.util.function.Function proxyResolver = RedirectHandlerOption.getProxyResolver(mProxySelector); redirectOption .scrubSensitiveHeaders() - .scrubHeaders(requestBuilder, requestUrl, locationUrl, proxyResolver); + .scrubHeaders(requestBuilder, requestUrl, proxyResolver); // Response status code 303 See Other then POST changes to GET if (userResponse.code() == HTTP_SEE_OTHER) { requestBuilder.method("GET", null); } - return requestBuilder.url(locationUrl).build(); + return requestBuilder.build(); } // Intercept request and response made to network diff --git a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/options/RedirectHandlerOption.java b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/options/RedirectHandlerOption.java index dd6e56f2a..e4ed395b5 100644 --- a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/options/RedirectHandlerOption.java +++ b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/options/RedirectHandlerOption.java @@ -49,32 +49,34 @@ public interface IScrubSensitiveHeaders { * Scrubs sensitive headers from the request before following a redirect. * @param requestBuilder The request builder to modify * @param originalUrl The original request URL - * @param newUrl The new redirect URL * @param proxyResolver A function that returns the proxy for a given destination, or null if no proxy applies */ void scrubHeaders( @Nonnull Request.Builder requestBuilder, @Nonnull HttpUrl originalUrl, - @Nonnull HttpUrl newUrl, @Nullable Function proxyResolver); } /** * The default implementation for scrubbing sensitive headers during redirects. - * This method removes Authorization and Cookie headers when the host or scheme changes, + * This method removes Authorization and Cookie headers when the host, scheme, or port changes, * and removes Proxy-Authorization headers when no proxy is configured or the proxy is bypassed for the new URL. */ @Nonnull public static final IScrubSensitiveHeaders DEFAULT_SCRUB_SENSITIVE_HEADERS = - (requestBuilder, originalUrl, newUrl, proxyResolver) -> { + (requestBuilder, originalUrl, proxyResolver) -> { Objects.requireNonNull(requestBuilder, "parameter requestBuilder cannot be null"); Objects.requireNonNull(originalUrl, "parameter originalUrl cannot be null"); - Objects.requireNonNull(newUrl, "parameter newUrl cannot be null"); - // Remove Authorization and Cookie headers if the request's scheme or host changes - boolean isDifferentHostOrScheme = + // Get the new URL from the request builder + HttpUrl newUrl = requestBuilder.build().url(); + Objects.requireNonNull(newUrl, "The request URL cannot be null"); + + // Remove Authorization and Cookie headers if the request's scheme, host, or port changes + boolean isDifferentOrigin = !newUrl.host().equalsIgnoreCase(originalUrl.host()) - || !newUrl.scheme().equalsIgnoreCase(originalUrl.scheme()); - if (isDifferentHostOrScheme) { + || !newUrl.scheme().equalsIgnoreCase(originalUrl.scheme()) + || newUrl.port() != originalUrl.port(); + if (isDifferentOrigin) { requestBuilder.removeHeader("Authorization"); requestBuilder.removeHeader("Cookie"); } diff --git a/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java b/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java index 9a32f8573..76299e574 100644 --- a/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java +++ b/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java @@ -266,6 +266,68 @@ void schemeChangeStripsAuthHeaders() throws Exception { assertNull(result.header("Proxy-Authorization")); // stripped (no proxy) } + @Test + void redirectWithDifferentPortRemovesAuthAndCookie() throws Exception { + Request original = + new Request.Builder() + .url("http://example.org:8080/foo") + .addHeader("Authorization", "Bearer token") + .addHeader("Cookie", "session=SECRET") + .build(); + Response redirect = + new Response.Builder() + .request(original) + .protocol(Protocol.HTTP_1_1) + .code(301) + .message("Moved Permanently") + .header("Location", "http://example.org:9090/bar") + .body(ResponseBody.create("", MediaType.parse("text/plain"))) + .build(); + + // Mock chain without proxy + Interceptor.Chain chain = mock(Interceptor.Chain.class); + + RedirectHandlerOption option = new RedirectHandlerOption(); + Request result = new RedirectHandler().getRedirect(original, redirect, option, chain); + + assertNotNull(result); + assertEquals("example.org", result.url().host()); + assertEquals(9090, result.url().port()); + assertNull(result.header("Authorization")); // stripped (port changed) + assertNull(result.header("Cookie")); // stripped (port changed) + } + + @Test + void redirectWithSamePortKeepsAuthAndCookie() throws Exception { + Request original = + new Request.Builder() + .url("http://example.org:8080/foo") + .addHeader("Authorization", "Bearer token") + .addHeader("Cookie", "session=SECRET") + .build(); + Response redirect = + new Response.Builder() + .request(original) + .protocol(Protocol.HTTP_1_1) + .code(302) + .message("Found") + .header("Location", "http://example.org:8080/bar") + .body(ResponseBody.create("", MediaType.parse("text/plain"))) + .build(); + + // Mock chain without proxy + Interceptor.Chain chain = mock(Interceptor.Chain.class); + + RedirectHandlerOption option = new RedirectHandlerOption(); + Request result = new RedirectHandler().getRedirect(original, redirect, option, chain); + + assertNotNull(result); + assertEquals("example.org", result.url().host()); + assertEquals(8080, result.url().port()); + assertNotNull(result.header("Authorization")); // kept (same port) + assertNotNull(result.header("Cookie")); // kept (same port) + } + @Test void customScrubberIsUsed() throws Exception { Request original = @@ -286,7 +348,7 @@ void customScrubberIsUsed() throws Exception { // Custom scrubber that never removes headers RedirectHandlerOption.IScrubSensitiveHeaders customScrubber = - (requestBuilder, originalUrl, newUrl, proxyResolver) -> { + (requestBuilder, originalUrl, proxyResolver) -> { // Don't remove any headers }; From fba3225c1c44b55da777e7ce9d245a4d32ebb356 Mon Sep 17 00:00:00 2001 From: Adrian Date: Mon, 2 Mar 2026 11:14:50 -0600 Subject: [PATCH 13/18] updating tests --- .../microsoft/kiota/http/middleware/RedirectHandlerTests.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java b/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java index 764105e8d..19b51b4ce 100644 --- a/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java +++ b/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java @@ -386,10 +386,10 @@ void customScrubberRemovesCustomHeaders() throws Exception { // Custom scrubber that removes custom headers in addition to the defaults RedirectHandlerOption.IScrubSensitiveHeaders customScrubber = - (requestBuilder, originalUrl, newUrl, proxyResolver) -> { + (requestBuilder, originalUrl, proxyResolver) -> { // Apply default scrubbing first RedirectHandlerOption.DEFAULT_SCRUB_SENSITIVE_HEADERS.scrubHeaders( - requestBuilder, originalUrl, newUrl, proxyResolver); + requestBuilder, originalUrl, proxyResolver); // Also remove application-specific sensitive headers requestBuilder.removeHeader("X-Custom-Secret"); requestBuilder.removeHeader("X-Api-Key"); From 5ea94b4487d929b871d7e6a3279c4b5cf1602904 Mon Sep 17 00:00:00 2001 From: Adrian Date: Mon, 2 Mar 2026 11:29:00 -0600 Subject: [PATCH 14/18] linter fix --- .../kiota/http/middleware/options/RedirectHandlerOption.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/options/RedirectHandlerOption.java b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/options/RedirectHandlerOption.java index e4ed395b5..d81e58b5a 100644 --- a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/options/RedirectHandlerOption.java +++ b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/options/RedirectHandlerOption.java @@ -71,7 +71,8 @@ void scrubHeaders( HttpUrl newUrl = requestBuilder.build().url(); Objects.requireNonNull(newUrl, "The request URL cannot be null"); - // Remove Authorization and Cookie headers if the request's scheme, host, or port changes + // Remove Authorization and Cookie headers if the request's scheme, host, or port + // changes boolean isDifferentOrigin = !newUrl.host().equalsIgnoreCase(originalUrl.host()) || !newUrl.scheme().equalsIgnoreCase(originalUrl.scheme()) From f05303d6adc7e1282f374008b28586f38f85c8b5 Mon Sep 17 00:00:00 2001 From: Adrian Date: Mon, 2 Mar 2026 12:23:02 -0600 Subject: [PATCH 15/18] Update components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java Co-authored-by: Vincent Biret --- .../com/microsoft/kiota/http/middleware/RedirectHandler.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java index f5d9f2c20..58e120e16 100644 --- a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java +++ b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java @@ -98,8 +98,7 @@ boolean isRedirected( Request getRedirect( final Request request, final Response userResponse, - final RedirectHandlerOption redirectOption, - final Chain chain) + final RedirectHandlerOption redirectOption) throws ProtocolException { String location = userResponse.header("Location"); if (location == null || location.length() == 0) return null; From 7f3779011f8eac3dfc21cc6f8fbedcac28839d0f Mon Sep 17 00:00:00 2001 From: Adrian Date: Mon, 2 Mar 2026 12:28:51 -0600 Subject: [PATCH 16/18] updating code review changes --- .../kiota/http/middleware/RedirectHandler.java | 2 +- .../http/middleware/RedirectHandlerTests.java | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java index 58e120e16..3dcd109ff 100644 --- a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java +++ b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java @@ -179,7 +179,7 @@ Request getRedirect( final Request followup = shouldRedirect - ? getRedirect(request, response, redirectOption, chain) + ? getRedirect(request, response, redirectOption) : null; if (followup != null) { response.close(); diff --git a/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java b/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java index 19b51b4ce..968273232 100644 --- a/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java +++ b/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java @@ -85,7 +85,7 @@ void crossHostRedirectStripsAuthHeaders() throws Exception { Interceptor.Chain chain = mock(Interceptor.Chain.class); RedirectHandlerOption option = new RedirectHandlerOption(); - Request result = new RedirectHandler().getRedirect(original, redirect, option, chain); + Request result = new RedirectHandler().getRedirect(original, redirect, option); assertNotNull(result); assertEquals("evil.attacker.com", result.url().host()); assertNull(result.header("Authorization")); // stripped (good) @@ -145,7 +145,7 @@ void sameHostRedirectKeepsAllHeaders() throws Exception { RedirectHandlerOption option = new RedirectHandlerOption(); Request result = new RedirectHandler(option, proxySelector) - .getRedirect(original, redirect, option, chain); + .getRedirect(original, redirect, option); assertNotNull(result); assertEquals("trusted.example.com", result.url().host()); @@ -182,7 +182,7 @@ void crossHostRedirectWithProxyKeepsProxyAuth() throws Exception { RedirectHandlerOption option = new RedirectHandlerOption(); Request result = new RedirectHandler(option, proxySelector) - .getRedirect(original, redirect, option, chain); + .getRedirect(original, redirect, option); assertNotNull(result); assertEquals("other.example.com", result.url().host()); @@ -220,7 +220,7 @@ void crossHostRedirectWithDirectProxyStripsProxyAuth() throws Exception { RedirectHandlerOption option = new RedirectHandlerOption(); Request result = new RedirectHandler(option, proxySelector) - .getRedirect(original, redirect, option, chain); + .getRedirect(original, redirect, option); assertNotNull(result); assertEquals("other.example.com", result.url().host()); @@ -256,7 +256,7 @@ void schemeChangeStripsAuthHeaders() throws Exception { Interceptor.Chain chain = mock(Interceptor.Chain.class); RedirectHandlerOption option = new RedirectHandlerOption(); - Request result = new RedirectHandler().getRedirect(original, redirect, option, chain); + Request result = new RedirectHandler().getRedirect(original, redirect, option); assertNotNull(result); assertEquals("trusted.example.com", result.url().host()); @@ -288,7 +288,7 @@ void redirectWithDifferentPortRemovesAuthAndCookie() throws Exception { Interceptor.Chain chain = mock(Interceptor.Chain.class); RedirectHandlerOption option = new RedirectHandlerOption(); - Request result = new RedirectHandler().getRedirect(original, redirect, option, chain); + Request result = new RedirectHandler().getRedirect(original, redirect, option); assertNotNull(result); assertEquals("example.org", result.url().host()); @@ -319,7 +319,7 @@ void redirectWithSamePortKeepsAuthAndCookie() throws Exception { Interceptor.Chain chain = mock(Interceptor.Chain.class); RedirectHandlerOption option = new RedirectHandlerOption(); - Request result = new RedirectHandler().getRedirect(original, redirect, option, chain); + Request result = new RedirectHandler().getRedirect(original, redirect, option); assertNotNull(result); assertEquals("example.org", result.url().host()); @@ -356,7 +356,7 @@ void customScrubberIsUsed() throws Exception { Interceptor.Chain chain = mock(Interceptor.Chain.class); RedirectHandlerOption option = new RedirectHandlerOption(5, null, customScrubber); - Request result = new RedirectHandler().getRedirect(original, redirect, option, chain); + Request result = new RedirectHandler().getRedirect(original, redirect, option); assertNotNull(result); assertEquals("other.example.com", result.url().host()); @@ -398,7 +398,7 @@ void customScrubberRemovesCustomHeaders() throws Exception { Interceptor.Chain chain = mock(Interceptor.Chain.class); RedirectHandlerOption option = new RedirectHandlerOption(5, null, customScrubber); - Request result = new RedirectHandler().getRedirect(original, redirect, option, chain); + Request result = new RedirectHandler().getRedirect(original, redirect, option); assertNotNull(result); assertEquals("other.example.com", result.url().host()); From 30bd8aeb9045781b5b6abe390e4ef0d78d4e7dc2 Mon Sep 17 00:00:00 2001 From: Adrian Date: Mon, 2 Mar 2026 14:03:39 -0600 Subject: [PATCH 17/18] Fixing test and format --- .../http/middleware/RedirectHandler.java | 4 +-- .../http/middleware/RedirectHandlerTests.java | 30 ++++--------------- 2 files changed, 7 insertions(+), 27 deletions(-) diff --git a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java index 3dcd109ff..543109aeb 100644 --- a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java +++ b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RedirectHandler.java @@ -178,9 +178,7 @@ Request getRedirect( && redirectOption.shouldRedirect().shouldRedirect(response); final Request followup = - shouldRedirect - ? getRedirect(request, response, redirectOption) - : null; + shouldRedirect ? getRedirect(request, response, redirectOption) : null; if (followup != null) { response.close(); request = followup; diff --git a/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java b/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java index 968273232..f7d601a55 100644 --- a/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java +++ b/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java @@ -81,8 +81,6 @@ void crossHostRedirectStripsAuthHeaders() throws Exception { .body(ResponseBody.create("", MediaType.parse("text/plain"))) .build(); - // Mock chain to get client without proxy - Interceptor.Chain chain = mock(Interceptor.Chain.class); RedirectHandlerOption option = new RedirectHandlerOption(); Request result = new RedirectHandler().getRedirect(original, redirect, option); @@ -136,16 +134,14 @@ void sameHostRedirectKeepsAllHeaders() throws Exception { .body(ResponseBody.create("", MediaType.parse("text/plain"))) .build(); - // Mock chain with proxy - Interceptor.Chain chain = mock(Interceptor.Chain.class); + // Setup proxy selector ProxySelector proxySelector = mock(ProxySelector.class); Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy.example.com", 8080)); when(proxySelector.select(any(URI.class))).thenReturn(Collections.singletonList(proxy)); RedirectHandlerOption option = new RedirectHandlerOption(); Request result = - new RedirectHandler(option, proxySelector) - .getRedirect(original, redirect, option); + new RedirectHandler(option, proxySelector).getRedirect(original, redirect, option); assertNotNull(result); assertEquals("trusted.example.com", result.url().host()); @@ -173,16 +169,14 @@ void crossHostRedirectWithProxyKeepsProxyAuth() throws Exception { .body(ResponseBody.create("", MediaType.parse("text/plain"))) .build(); - // Mock chain with active proxy - Interceptor.Chain chain = mock(Interceptor.Chain.class); + // Setup proxy selector with active proxy ProxySelector proxySelector = mock(ProxySelector.class); Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy.example.com", 8080)); when(proxySelector.select(any(URI.class))).thenReturn(Collections.singletonList(proxy)); RedirectHandlerOption option = new RedirectHandlerOption(); Request result = - new RedirectHandler(option, proxySelector) - .getRedirect(original, redirect, option); + new RedirectHandler(option, proxySelector).getRedirect(original, redirect, option); assertNotNull(result); assertEquals("other.example.com", result.url().host()); @@ -211,16 +205,14 @@ void crossHostRedirectWithDirectProxyStripsProxyAuth() throws Exception { .body(ResponseBody.create("", MediaType.parse("text/plain"))) .build(); - // Mock chain with DIRECT proxy (no proxy) - Interceptor.Chain chain = mock(Interceptor.Chain.class); + // Setup proxy selector with DIRECT proxy (no proxy) ProxySelector proxySelector = mock(ProxySelector.class); when(proxySelector.select(any(URI.class))) .thenReturn(Collections.singletonList(Proxy.NO_PROXY)); RedirectHandlerOption option = new RedirectHandlerOption(); Request result = - new RedirectHandler(option, proxySelector) - .getRedirect(original, redirect, option); + new RedirectHandler(option, proxySelector).getRedirect(original, redirect, option); assertNotNull(result); assertEquals("other.example.com", result.url().host()); @@ -252,8 +244,6 @@ void schemeChangeStripsAuthHeaders() throws Exception { .body(ResponseBody.create("", MediaType.parse("text/plain"))) .build(); - // Mock chain without proxy - Interceptor.Chain chain = mock(Interceptor.Chain.class); RedirectHandlerOption option = new RedirectHandlerOption(); Request result = new RedirectHandler().getRedirect(original, redirect, option); @@ -284,8 +274,6 @@ void redirectWithDifferentPortRemovesAuthAndCookie() throws Exception { .body(ResponseBody.create("", MediaType.parse("text/plain"))) .build(); - // Mock chain without proxy - Interceptor.Chain chain = mock(Interceptor.Chain.class); RedirectHandlerOption option = new RedirectHandlerOption(); Request result = new RedirectHandler().getRedirect(original, redirect, option); @@ -315,8 +303,6 @@ void redirectWithSamePortKeepsAuthAndCookie() throws Exception { .body(ResponseBody.create("", MediaType.parse("text/plain"))) .build(); - // Mock chain without proxy - Interceptor.Chain chain = mock(Interceptor.Chain.class); RedirectHandlerOption option = new RedirectHandlerOption(); Request result = new RedirectHandler().getRedirect(original, redirect, option); @@ -352,9 +338,6 @@ void customScrubberIsUsed() throws Exception { // Don't remove any headers }; - // Mock chain - Interceptor.Chain chain = mock(Interceptor.Chain.class); - RedirectHandlerOption option = new RedirectHandlerOption(5, null, customScrubber); Request result = new RedirectHandler().getRedirect(original, redirect, option); @@ -395,7 +378,6 @@ void customScrubberRemovesCustomHeaders() throws Exception { requestBuilder.removeHeader("X-Api-Key"); }; - Interceptor.Chain chain = mock(Interceptor.Chain.class); RedirectHandlerOption option = new RedirectHandlerOption(5, null, customScrubber); Request result = new RedirectHandler().getRedirect(original, redirect, option); From 9b590c8c9e4405f567a545ba52f3f69e89488c04 Mon Sep 17 00:00:00 2001 From: Adrian Date: Mon, 2 Mar 2026 14:15:51 -0600 Subject: [PATCH 18/18] linting --- .../kiota/http/middleware/RedirectHandlerTests.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java b/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java index f7d601a55..59277d800 100644 --- a/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java +++ b/components/http/okHttp/src/test/java/com/microsoft/kiota/http/middleware/RedirectHandlerTests.java @@ -81,7 +81,6 @@ void crossHostRedirectStripsAuthHeaders() throws Exception { .body(ResponseBody.create("", MediaType.parse("text/plain"))) .build(); - RedirectHandlerOption option = new RedirectHandlerOption(); Request result = new RedirectHandler().getRedirect(original, redirect, option); assertNotNull(result); @@ -244,7 +243,6 @@ void schemeChangeStripsAuthHeaders() throws Exception { .body(ResponseBody.create("", MediaType.parse("text/plain"))) .build(); - RedirectHandlerOption option = new RedirectHandlerOption(); Request result = new RedirectHandler().getRedirect(original, redirect, option); @@ -274,7 +272,6 @@ void redirectWithDifferentPortRemovesAuthAndCookie() throws Exception { .body(ResponseBody.create("", MediaType.parse("text/plain"))) .build(); - RedirectHandlerOption option = new RedirectHandlerOption(); Request result = new RedirectHandler().getRedirect(original, redirect, option); @@ -303,7 +300,6 @@ void redirectWithSamePortKeepsAuthAndCookie() throws Exception { .body(ResponseBody.create("", MediaType.parse("text/plain"))) .build(); - RedirectHandlerOption option = new RedirectHandlerOption(); Request result = new RedirectHandler().getRedirect(original, redirect, option); @@ -378,7 +374,6 @@ void customScrubberRemovesCustomHeaders() throws Exception { requestBuilder.removeHeader("X-Api-Key"); }; - RedirectHandlerOption option = new RedirectHandlerOption(5, null, customScrubber); Request result = new RedirectHandler().getRedirect(original, redirect, option);