renathy
renathy

Reputation: 5345

Add custom BasicAuthenticationHandler in .NET Core - problems injection necessary services into handler

I have to add our custom Basic Authentication Handler, but our implementation requires to pass parameter to it. I am not able to achieve this using DI. Here is part of the code:

    // Part of ConfigureServices in Startup.cs
    public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        ...
        // Some DIs in ConfigureService
        services.AddTransient<ICustomService, CustomService>(); //this should be passed later to handler
        services.AddHttpContextAccessor();
        ...
        // Adding authentication in ConfigureServices
        services.AddAuthentication("Basic")
            .AddScheme<CustomBasicAuthenticationOptions, CustomBasicAuthenticationHandler>(
            "Basic",
            options => new CustomBasicAuthenticationOptions()
            {
                CustomService = ??? // HOW OT GET CustomService: ICustomService from Container here?
            });
      ...
   }

   // CustomBasicAuthenticationOptions
   public class CustomBasicAuthenticationOptions : AuthenticationSchemeOptions
   {
       public CustomBasicAuthenticationOptions();
       public static string AuthenticationScheme { get; }
       public ICustomService CustomService { get; set; }  //THIS SHOULD BE INJECTED HERE during AddAuthentication?! How?
       ...
   }

   // CustomService and its constructor of 
   public class CustomService : ICustomService 
   {
       public CustomService(IHttpContextAccessor httpContextAccessor) {
          ...
       }
   }

Upvotes: 1

Views: 503

Answers (1)

Nkosi
Nkosi

Reputation: 246998

You comment in the original example shows what actually depends on the service

// this should be passed later to handler

Move the service over to the handler as an explicit dependency via constructor injection.

public class CustomBasicAuthenticationHandler : AuthenticationHandler<CustomBasicAuthenticationOptions> {
    private readonly ICustomService customService;

    public CustomBasicAuthenticationHandler(
        ICustomService customService, //<-- NOTE
        IOptionsMonitor<BasicAuthenticationOptions> options,
        ILoggerFactory logger,
        UrlEncoder encoder,
        ISystemClock clock
    )
    : base(options, logger, encoder, clock) {
        this.customService = customService;
    }

    //...
}

And refactor the registration

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    //...

    // Some DIs in ConfigureService
    services.AddTransient<ICustomService, CustomService>(); //this should be passed later to handler
    services.AddHttpContextAccessor();

    //...

    // Adding authentication in ConfigureServices
    services.AddAuthentication("Basic")
        .AddScheme<CustomBasicAuthenticationOptions, CustomBasicAuthenticationHandler>("Basic", null);

    //...
}

Upvotes: 1

Related Questions