diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.Security/ServiceCollectionExtensions.cs b/src/Server/ZB.MOM.WW.OtOpcUa.Security/ServiceCollectionExtensions.cs
index 657c794..4dbc1e9 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.Security/ServiceCollectionExtensions.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.Security/ServiceCollectionExtensions.cs
@@ -11,6 +11,23 @@ using ZB.MOM.WW.OtOpcUa.Security.Ldap;
namespace ZB.MOM.WW.OtOpcUa.Security;
+///
+/// Resolves from the real DI container at runtime so the bearer
+/// pipeline's stay in
+/// lock-step with . Replaces the prior
+/// services.BuildServiceProvider() antipattern (ASP0000) that built a captive provider
+/// from inside .AddJwtBearer.
+///
+internal sealed class ConfigureJwtBearerFromTokenService(JwtTokenService tokenService)
+ : IPostConfigureOptions
+{
+ public void PostConfigure(string? name, JwtBearerOptions options)
+ {
+ if (name != JwtBearerDefaults.AuthenticationScheme) return;
+ options.TokenValidationParameters = tokenService.BuildValidationParameters();
+ }
+}
+
public static class ServiceCollectionExtensions
{
///
@@ -52,12 +69,9 @@ public static class ServiceCollectionExtensions
return Task.CompletedTask;
};
})
- .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, o =>
- {
- using var scope = services.BuildServiceProvider().CreateScope();
- var jwt = scope.ServiceProvider.GetRequiredService();
- o.TokenValidationParameters = jwt.BuildValidationParameters();
- });
+ .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, _ => { /* parameters set by IPostConfigureOptions below */ });
+
+ services.AddSingleton, ConfigureJwtBearerFromTokenService>();
services.AddAuthorization(o =>
{