Skip to content
Open
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
"Kiota"
],
"editor.formatOnSave": true,
"dotnet-test-explorer.testProjectPath": "**/*.Tests.csproj"
"dotnet-test-explorer.testProjectPath": "**/*.Tests.csproj",
"sarif-viewer.connectToGithubCodeScanning": "on"
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// ------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Net.Http;
using Microsoft.Kiota.Abstractions;

Expand Down Expand Up @@ -44,5 +45,12 @@ public int MaxRedirect
/// A boolean value to determine if we redirects are allowed if the scheme changes(e.g. https to http). Defaults to false.
/// </summary>
public bool AllowRedirectOnSchemeChange { get; set; } = false;

/// <summary>
/// A collection of header names that should be removed when the host or scheme changes during a redirect.
/// This is useful for removing sensitive headers like API keys that should not be sent to different hosts.
/// The Authorization and Cookie headers are always removed on host/scheme change regardless of this setting.
/// </summary>
public ICollection<string> SensitiveHeaders { get; set; } = new List<string>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't we say this would be a call back with the header name and the new origin? (And potentially the old one)

If not, it should at the very least be a hashset with ordinal case insensitive string comparer

}
}
66 changes: 63 additions & 3 deletions src/http/httpClient/Middleware/RedirectHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information.
// ------------------------------------------------------------------------------

using Microsoft.Kiota.Http.HttpClientLibrary.Extensions;
using Microsoft.Kiota.Http.HttpClientLibrary.Middleware.Options;
using System;
using System.Diagnostics;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Kiota.Http.HttpClientLibrary.Extensions;
using Microsoft.Kiota.Http.HttpClientLibrary.Middleware.Options;

namespace Microsoft.Kiota.Http.HttpClientLibrary.Middleware
{
Expand Down Expand Up @@ -41,7 +41,7 @@
/// <param name="request">The <see cref="HttpRequestMessage"/> to send.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/>for the request.</param>
/// <returns>The <see cref="HttpResponseMessage"/>.</returns>
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)

Check warning on line 44 in src/http/httpClient/Middleware/RedirectHandler.cs

View workflow job for this annotation

GitHub Actions / Build

Refactor this method to reduce its Cognitive Complexity from 46 to the 15 allowed. (https://rules.sonarsource.com/csharp/RSPEC-3776)

Check warning on line 44 in src/http/httpClient/Middleware/RedirectHandler.cs

View workflow job for this annotation

GitHub Actions / Build

Refactor this method to reduce its Cognitive Complexity from 46 to the 15 allowed. (https://rules.sonarsource.com/csharp/RSPEC-3776)

Check warning on line 44 in src/http/httpClient/Middleware/RedirectHandler.cs

View workflow job for this annotation

GitHub Actions / Build

Refactor this method to reduce its Cognitive Complexity from 46 to the 15 allowed. (https://rules.sonarsource.com/csharp/RSPEC-3776)

Check warning on line 44 in src/http/httpClient/Middleware/RedirectHandler.cs

View workflow job for this annotation

GitHub Actions / Build

Refactor this method to reduce its Cognitive Complexity from 46 to the 15 allowed. (https://rules.sonarsource.com/csharp/RSPEC-3776)

Check warning on line 44 in src/http/httpClient/Middleware/RedirectHandler.cs

View workflow job for this annotation

GitHub Actions / Build

Refactor this method to reduce its Cognitive Complexity from 46 to the 15 allowed. (https://rules.sonarsource.com/csharp/RSPEC-3776)
{
if(request == null) throw new ArgumentNullException(nameof(request));

Expand Down Expand Up @@ -119,11 +119,28 @@
newRequest.RequestUri = new Uri(baseAddress + response.Headers.Location);
}

// Remove Auth if http request's scheme or host changes
// Remove Authorization and Cookie header if http request's scheme or host changes
if(!newRequest.RequestUri.Host.Equals(request.RequestUri?.Host) ||
!newRequest.RequestUri.Scheme.Equals(request.RequestUri?.Scheme))
{
newRequest.Headers.Authorization = null;
newRequest.Headers.Remove("Cookie");

// Remove any additional sensitive headers configured in the options
if(redirectOption.SensitiveHeaders.Count > 0)
{
foreach(var header in redirectOption.SensitiveHeaders)
{
newRequest.Headers.Remove(header);
}
}
}

// Remove ProxyAuthorization if no proxy is configured or the URL is bypassed
var proxyResolver = GetProxyResolver();
if(proxyResolver == null || proxyResolver(newRequest.RequestUri) == null)
{
newRequest.Headers.ProxyAuthorization = null;
}

// If scheme has changed. Ensure that this has been opted in for security reasons
Expand Down Expand Up @@ -160,7 +177,7 @@
}
}

private bool ShouldRedirect(HttpResponseMessage responseMessage, RedirectHandlerOption redirectOption)

Check warning on line 180 in src/http/httpClient/Middleware/RedirectHandler.cs

View workflow job for this annotation

GitHub Actions / Build

Make 'ShouldRedirect' a static method. (https://rules.sonarsource.com/csharp/RSPEC-2325)

Check warning on line 180 in src/http/httpClient/Middleware/RedirectHandler.cs

View workflow job for this annotation

GitHub Actions / Build

Make 'ShouldRedirect' a static method. (https://rules.sonarsource.com/csharp/RSPEC-2325)

Check warning on line 180 in src/http/httpClient/Middleware/RedirectHandler.cs

View workflow job for this annotation

GitHub Actions / Build

Make 'ShouldRedirect' a static method. (https://rules.sonarsource.com/csharp/RSPEC-2325)

Check warning on line 180 in src/http/httpClient/Middleware/RedirectHandler.cs

View workflow job for this annotation

GitHub Actions / Build

Make 'ShouldRedirect' a static method. (https://rules.sonarsource.com/csharp/RSPEC-2325)
{
return IsRedirect(responseMessage.StatusCode) && redirectOption.ShouldRedirect(responseMessage) && redirectOption.MaxRedirect > 0;
}
Expand All @@ -183,5 +200,48 @@
};
}

/// <summary>
/// Gets a callback that resolves the proxy URI for a given destination URI.
/// </summary>
/// <returns>A function that takes a destination URI and returns the proxy URI, or null if no proxy is configured or the destination is bypassed.</returns>
private Func<Uri, Uri?>? GetProxyResolver()
{
var proxy = GetProxyFromFinalHandler();
if(proxy == null)
return null;
return destination => proxy.IsBypassed(destination) ? null : proxy.GetProxy(destination);
}

/// <summary>
/// Traverses the handler chain to find the final handler and extract its proxy settings.
/// </summary>
/// <returns>The IWebProxy from the final handler, or null if not found.</returns>
private IWebProxy? GetProxyFromFinalHandler()

Check warning on line 219 in src/http/httpClient/Middleware/RedirectHandler.cs

View workflow job for this annotation

GitHub Actions / Build

Make 'GetProxyFromFinalHandler' a static method. (https://rules.sonarsource.com/csharp/RSPEC-2325)
{
#if BROWSER
// Browser platform does not support proxy configuration
return null;
#else
var handler = InnerHandler;
while(handler != null)
{
#if NETFRAMEWORK
if(handler is WinHttpHandler winHttpHandler)
return winHttpHandler.Proxy;
#endif
#if NET5_0_OR_GREATER
if(handler is SocketsHttpHandler socketsHandler)
return socketsHandler.Proxy;
#endif
if(handler is HttpClientHandler httpClientHandler)
return httpClientHandler.Proxy;
if(handler is DelegatingHandler delegatingHandler)
handler = delegatingHandler.InnerHandler;
else
break;
}
return null;
#endif
}
}
}
Loading
Loading