diff --git a/bitwarden_license/src/Scim/Startup.cs b/bitwarden_license/src/Scim/Startup.cs index edbbf34aea..b4149503ae 100644 --- a/bitwarden_license/src/Scim/Startup.cs +++ b/bitwarden_license/src/Scim/Startup.cs @@ -89,6 +89,9 @@ public class Startup services.AddScimGroupQueries(); services.AddScimUserQueries(); 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( diff --git a/bitwarden_license/src/Sso/Startup.cs b/bitwarden_license/src/Sso/Startup.cs index 3aeb9c6beb..a8f8109cb4 100644 --- a/bitwarden_license/src/Sso/Startup.cs +++ b/bitwarden_license/src/Sso/Startup.cs @@ -86,6 +86,9 @@ public class Startup // TODO: Remove when OrganizationUser methods are moved out of OrganizationService, this noop dependency should // TODO: no longer be required - see PM-1880 services.AddScoped(); + + // This should be registered last because it customizes the primary http message handler and we want it to win. + services.AddX509ChainCustomization(); } public void Configure( diff --git a/bitwarden_license/src/Sso/Utilities/DynamicAuthenticationSchemeProvider.cs b/bitwarden_license/src/Sso/Utilities/DynamicAuthenticationSchemeProvider.cs index 804a323109..72ed946f76 100644 --- a/bitwarden_license/src/Sso/Utilities/DynamicAuthenticationSchemeProvider.cs +++ b/bitwarden_license/src/Sso/Utilities/DynamicAuthenticationSchemeProvider.cs @@ -35,7 +35,7 @@ public class DynamicAuthenticationSchemeProvider : AuthenticationSchemeProvider private readonly Dictionary _cachedHandlerSchemes; private readonly SemaphoreSlim _semaphore; private readonly IServiceProvider _serviceProvider; - + private readonly IHttpMessageHandlerFactory _httpMessageHandlerFactory; private DateTime? _lastSchemeLoad; private IEnumerable _schemesCopy = Array.Empty(); private IEnumerable _handlerSchemesCopy = Array.Empty(); @@ -50,7 +50,8 @@ public class DynamicAuthenticationSchemeProvider : AuthenticationSchemeProvider ILogger logger, GlobalSettings globalSettings, SamlEnvironment samlEnvironment, - IServiceProvider serviceProvider) + IServiceProvider serviceProvider, + IHttpMessageHandlerFactory httpMessageHandlerFactory) : base(options) { _oidcPostConfigureOptions = oidcPostConfigureOptions; @@ -78,6 +79,7 @@ public class DynamicAuthenticationSchemeProvider : AuthenticationSchemeProvider _cachedHandlerSchemes = new Dictionary(); _semaphore = new SemaphoreSlim(1); _serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider)); + _httpMessageHandlerFactory = httpMessageHandlerFactory; } private bool CacheIsValid @@ -310,6 +312,8 @@ public class DynamicAuthenticationSchemeProvider : AuthenticationSchemeProvider // Prevents URLs that go beyond 1024 characters which may break for some servers AuthenticationMethod = config.RedirectBehavior, GetClaimsFromUserInfoEndpoint = config.GetClaimsFromUserInfoEndpoint, + // Make sure all communication goes through the Platform supplied HttpMessageHandler + BackchannelHttpHandler = _httpMessageHandlerFactory.CreateHandler(), }; oidcOptions.Scope .AddIfNotExists(OpenIdConnectScopes.OpenId) diff --git a/src/Admin/Startup.cs b/src/Admin/Startup.cs index 11f9e7ce68..b4ed9c5457 100644 --- a/src/Admin/Startup.cs +++ b/src/Admin/Startup.cs @@ -129,6 +129,9 @@ public class Startup services.AddHostedService(); } } + + // This should be registered last because it customizes the primary http message handler and we want it to win. + services.AddX509ChainCustomization(); } public void Configure( diff --git a/src/Api/Startup.cs b/src/Api/Startup.cs index deac7bf0c9..7f32ad7599 100644 --- a/src/Api/Startup.cs +++ b/src/Api/Startup.cs @@ -215,6 +215,9 @@ public class Startup { services.AddHostedService(); } + + // This should be registered last because it customizes the primary http message handler and we want it to win. + services.AddX509ChainCustomization(); } public void Configure( diff --git a/src/Billing/Startup.cs b/src/Billing/Startup.cs index afb01f4801..89ac840b14 100644 --- a/src/Billing/Startup.cs +++ b/src/Billing/Startup.cs @@ -121,6 +121,9 @@ public class Startup // Swagger services.AddEndpointsApiExplorer(); 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( diff --git a/src/Events/Startup.cs b/src/Events/Startup.cs index a9be60ce8a..5ba07952ba 100644 --- a/src/Events/Startup.cs +++ b/src/Events/Startup.cs @@ -130,6 +130,9 @@ public class Startup 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( diff --git a/src/EventsProcessor/Startup.cs b/src/EventsProcessor/Startup.cs index 65d1d36e24..9f956dc977 100644 --- a/src/EventsProcessor/Startup.cs +++ b/src/EventsProcessor/Startup.cs @@ -59,6 +59,9 @@ public class Startup } } services.AddHostedService(); + + // This should be registered last because it customizes the primary http message handler and we want it to win. + services.AddX509ChainCustomization(); } public void Configure( diff --git a/src/Icons/Startup.cs b/src/Icons/Startup.cs index 4695c320e9..a3ed0ddb67 100644 --- a/src/Icons/Startup.cs +++ b/src/Icons/Startup.cs @@ -47,6 +47,9 @@ public class Startup // Mvc 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( diff --git a/src/Identity/Startup.cs b/src/Identity/Startup.cs index 320c91b248..8b959deac0 100644 --- a/src/Identity/Startup.cs +++ b/src/Identity/Startup.cs @@ -163,6 +163,9 @@ public class Startup { 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( diff --git a/src/Notifications/Startup.cs b/src/Notifications/Startup.cs index c939d0d2fd..cb8fb576c0 100644 --- a/src/Notifications/Startup.cs +++ b/src/Notifications/Startup.cs @@ -76,6 +76,9 @@ public class Startup services.AddHostedService(); } } + + // This should be registered last because it customizes the primary http message handler and we want it to win. + services.AddX509ChainCustomization(); } public void Configure( diff --git a/src/SharedWeb/Utilities/ServiceCollectionExtensions.cs b/src/SharedWeb/Utilities/ServiceCollectionExtensions.cs index 144ea1f036..1169e29cec 100644 --- a/src/SharedWeb/Utilities/ServiceCollectionExtensions.cs +++ b/src/SharedWeb/Utilities/ServiceCollectionExtensions.cs @@ -483,6 +483,8 @@ public static class ServiceCollectionExtensions Action addAuthorization) { 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 => { options.MapInboundClaims = false; @@ -502,6 +504,15 @@ 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(JwtBearerDefaults.AuthenticationScheme) + .Configure((options, httpMessageHandlerFactory) => + { + options.BackchannelHttpHandler = httpMessageHandlerFactory.CreateHandler(); + }); + if (addAuthorization != null) { services.AddAuthorization(config =>