1
0
mirror of https://github.com/bitwarden/server.git synced 2025-05-03 02:32:16 -05:00

Use IHttpMessageHandlerFactory For HTTP Communication

Co-authored-by: Justin Baur <19896123+justindbaur@users.noreply.github.com>
This commit is contained in:
tangowithfoxtrot 2025-04-23 11:25:43 -07:00
parent 90d831d9ef
commit c93be6d52b
No known key found for this signature in database
12 changed files with 53 additions and 1 deletions

View File

@ -89,6 +89,9 @@ public class Startup
services.AddScimGroupQueries(); services.AddScimGroupQueries();
services.AddScimUserQueries(); services.AddScimUserQueries();
services.AddScimUserCommands(); services.AddScimUserCommands();
// This should be registered last because it customizes the primary http message handler and we want it to win.
services.AddX509ChainCustomization();
} }
public void Configure( public void Configure(

View File

@ -86,6 +86,9 @@ public class Startup
// TODO: Remove when OrganizationUser methods are moved out of OrganizationService, this noop dependency should // TODO: Remove when OrganizationUser methods are moved out of OrganizationService, this noop dependency should
// TODO: no longer be required - see PM-1880 // TODO: no longer be required - see PM-1880
services.AddScoped<IServiceAccountRepository, NoopServiceAccountRepository>(); services.AddScoped<IServiceAccountRepository, NoopServiceAccountRepository>();
// This should be registered last because it customizes the primary http message handler and we want it to win.
services.AddX509ChainCustomization();
} }
public void Configure( public void Configure(

View File

@ -35,6 +35,7 @@ public class DynamicAuthenticationSchemeProvider : AuthenticationSchemeProvider
private readonly Dictionary<string, DynamicAuthenticationScheme> _cachedHandlerSchemes; private readonly Dictionary<string, DynamicAuthenticationScheme> _cachedHandlerSchemes;
private readonly SemaphoreSlim _semaphore; private readonly SemaphoreSlim _semaphore;
private readonly IServiceProvider _serviceProvider; private readonly IServiceProvider _serviceProvider;
private readonly IHttpMessageHandlerFactory _httpMessageHandlerFactory;
private DateTime? _lastSchemeLoad; private DateTime? _lastSchemeLoad;
private IEnumerable<DynamicAuthenticationScheme> _schemesCopy = Array.Empty<DynamicAuthenticationScheme>(); private IEnumerable<DynamicAuthenticationScheme> _schemesCopy = Array.Empty<DynamicAuthenticationScheme>();

View File

@ -129,6 +129,9 @@ public class Startup
services.AddHostedService<HostedServices.AzureQueueMailHostedService>(); services.AddHostedService<HostedServices.AzureQueueMailHostedService>();
} }
} }
// This should be registered last because it customizes the primary http message handler and we want it to win.
services.AddX509ChainCustomization();
} }
public void Configure( public void Configure(

View File

@ -230,6 +230,9 @@ public class Startup
{ {
services.AddSingleton<ISlackService, NoopSlackService>(); services.AddSingleton<ISlackService, NoopSlackService>();
} }
// This should be registered last because it customizes the primary http message handler and we want it to win.
services.AddX509ChainCustomization();
} }
public void Configure( public void Configure(

View File

@ -121,6 +121,9 @@ public class Startup
// Swagger // Swagger
services.AddEndpointsApiExplorer(); services.AddEndpointsApiExplorer();
services.AddSwaggerGen(); services.AddSwaggerGen();
// This should be registered last because it customizes the primary http message handler and we want it to win.
services.AddX509ChainCustomization();
} }
public void Configure( public void Configure(

View File

@ -146,6 +146,9 @@ public class Startup
globalSettings, globalSettings,
globalSettings.EventLogging.RabbitMq.WebhookQueueName)); globalSettings.EventLogging.RabbitMq.WebhookQueueName));
} }
// This should be registered last because it customizes the primary http message handler and we want it to win.
services.AddX509ChainCustomization();
} }
public void Configure( public void Configure(

View File

@ -82,6 +82,9 @@ public class Startup
globalSettings.EventLogging.AzureServiceBus.WebhookSubscriptionName)); globalSettings.EventLogging.AzureServiceBus.WebhookSubscriptionName));
} }
services.AddHostedService<AzureQueueHostedService>(); services.AddHostedService<AzureQueueHostedService>();
// This should be registered last because it customizes the primary http message handler and we want it to win.
services.AddX509ChainCustomization();
} }
public void Configure( public void Configure(

View File

@ -47,6 +47,9 @@ public class Startup
// Mvc // Mvc
services.AddMvc(); services.AddMvc();
// This should be registered last because it customizes the primary http message handler and we want it to win.
services.AddX509ChainCustomization();
} }
public void Configure( public void Configure(

View File

@ -163,6 +163,9 @@ public class Startup
{ {
client.BaseAddress = new Uri(globalSettings.BaseServiceUri.InternalSso); client.BaseAddress = new Uri(globalSettings.BaseServiceUri.InternalSso);
}); });
// This should be registered last because it customizes the primary http message handler and we want it to win.
services.AddX509ChainCustomization();
} }
public void Configure( public void Configure(

View File

@ -76,6 +76,9 @@ public class Startup
services.AddHostedService<AzureQueueHostedService>(); services.AddHostedService<AzureQueueHostedService>();
} }
} }
// This should be registered last because it customizes the primary http message handler and we want it to win.
services.AddX509ChainCustomization();
} }
public void Configure( public void Configure(

View File

@ -1,4 +1,5 @@
using System.Net; using System.Diagnostics;
using System.Net;
using System.Reflection; using System.Reflection;
using System.Security.Claims; using System.Security.Claims;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
@ -486,6 +487,8 @@ public static class ServiceCollectionExtensions
Action<AuthorizationOptions> addAuthorization) Action<AuthorizationOptions> addAuthorization)
{ {
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
// If we ever use the overload here with a different authentication scheme name then
// we need to change the AddOptions call below.
.AddJwtBearer(options => .AddJwtBearer(options =>
{ {
options.MapInboundClaims = false; options.MapInboundClaims = false;
@ -505,6 +508,24 @@ public static class ServiceCollectionExtensions
}; };
}); });
// This is done through a Configure method instead of above so that we can avoid
// an early creation of services but still use a service that should centrally control how HttpMessageHandlers
// are created.
services.AddOptions<JwtBearerOptions>(JwtBearerDefaults.AuthenticationScheme)
.Configure<IHttpMessageHandlerFactory>((options, httpMessageHandlerFactory) =>
{
// Since we don't manually set the Backchannel and the Post stage configuration shouldn't have
// ran yet we don't expect this option to be set. If it is set, it was likely set with a
// handler already and won't respect the BackchannelHttpHandler we are about to set.
Debug.Assert(options.Backchannel is null);
// Do a few debug checks to make sure we are customizing the expected options configured above.
Debug.Assert(!options.TokenValidationParameters.ValidateAudience);
Debug.Assert(options.TokenValidationParameters.ValidTypes.Single() == "at+jwt");
Debug.Assert(options.TokenValidationParameters.NameClaimType == ClaimTypes.Email);
options.BackchannelHttpHandler = httpMessageHandlerFactory.CreateHandler();
});
if (addAuthorization != null) if (addAuthorization != null)
{ {
services.AddAuthorization(config => services.AddAuthorization(config =>