【问题标题】:How to inject services in an AddOpenIdConnect event (OnTokenValidated)?如何在 AddOpenIdConnect 事件(OnTokenValidated)中注入服务?
【发布时间】:2021-10-03 10:50:13
【问题描述】:

我需要编写需要ConfigureServices 才能完全执行的业务逻辑。 OnTokenValidated 本身位于 ConfigureServices 内部。

AddOpenIdConnect 中间件的替代品是什么,这样我就可以 Success 调用完全灵活地使用注入服务?

        services.AddAuthentication(options =>
        {
            options.DefaultScheme = "cookie";
            //...
        })
        .AddOpenIdConnect("oidc", options =>
        {
            options.Authority = "https://localhost:5001";
            /....
            options.Scope.Add("offline_access");

            options.Events.OnTokenValidated = async n =>
            {
                //Need other services which will only 
                //get injected once ConfigureServices method has fully executed.
            };
        }

参考:为什么 https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-5.0#ASP0000

【问题讨论】:

标签: c# asp.net-core identityserver4 duende-identity-server


【解决方案1】:

要在OnTokenValidated 事件处理程序中解析服务,您可以使用TokenValidatedContext.HttpContext.RequestServices

Events =
{
    OnTokenValidated = async context =>
    {
        var someService = context.HttpContext.RequestServices.GetRequiredService<ISomeService>();
        var result = await someService.DoSomethingAsync();
        // a custom callback
    }
}

【讨论】:

    【解决方案2】:

    您可以在运行时使用IAuthenticationSchemeProviderIOptionsMonitorCache 添加身份验证方案。

    public class AuthInitializer
    {
        private IAuthenticationSchemeProvider _provider;
        private IOptionsMonitorCache<OpenIdConnectOptions> _optionsCache;
        // other services you need
    
        public AuthInitializer(IAuthenticationSchemeProvider provider, IOptionsMonitorCache<OpenIdConnectOptions> options)
        {
            _provider = provider;
            _optionsCache = options;
        }
    
        public Task InitializeAsync(CancellationToken cancellationToken = default)
        {
            // execute some business logic
            // ...
    
            var schemeName = "OidcCustom1"; // must be unique for different schemes
            var schemeOptions = new OpenIdConnectOptions()
            {
                Authority = "https://demo.identityserver.io/",
                ClientId = "m2m", // fetch credentials from another service or database
                ClientSecret = "secret",
                Events = {
                    OnTokenValidated = async context => {
                        var someService = context.HttpContext.RequestServices.GetRequiredService<ISomeService>();
                        var result = await someService.DoSomethingAsync();
                        // handle the event
                    }
                }
            };
        
            var scheme = new AuthenticationScheme(schemeName, displayName:null, typeof(OpenIdConnectHandler));
            _provider.TryAddScheme(scheme);
            _optionsCache.TryAdd(
                schemeName,
                schemeOptions
            );
            return Task.CompletedTask;
        }
    }
    

    在 DI 中注册这个类:

    services.AddTransient<AuthInitializer>();
    

    然后在构建主机后执行它:

    public class Program
    {
        public static async Task Main(string[] args)
        {
            var host = CreateHostBuilder(args).Build();
            using var scope = host.Services.CreateScope();
            var authInitializer = scope.ServiceProvider.GetRequiredService<AuthInitializer>();
            await authInitializer.InitializeAsync();
            await host.RunAsync();
        }
    }
    

    那么你可以照常参考这个认证方案:

    services.AddAuthentication(
        options =>
        {
            options.DefaultScheme = "OidcCustom";
        });
    

    [Authorize(AuthenticationSchemes = "OidcCustom")]
    [HttpGet]
    public async Task<IActionResult> Index(CancellationToken cancellationToken) { ... }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-11-27
      • 2021-02-05
      • 1970-01-01
      • 2020-02-27
      • 1970-01-01
      • 2018-07-01
      • 1970-01-01
      相关资源
      最近更新 更多