Search code examples
c#asp.net-coresimple-injector

How to inject application service into AuthenticationHandler


I have a custom AuthenticationHandler<> implementation that depends on application service. Is there a way to resolve dependencies of AuthenticationHandler from Simple Injector? Or maybe cross-wire registration so that applications services can be resolved from IServiceCollection?

Sample implementation can look as follows for simplicity:

public class AuthHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
    private readonly ITokenDecryptor tokenDecryptor;

    public SecurityTokenAuthHandler(ITokenDecryptor tokenDecryptor,
        IOptionsMonitor<AuthenticationSchemeOptions> options, 
        ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) :
        base(options, logger, encoder, clock) =>
        this.tokenDecryptor = tokenDecryptor;

    protected override async Task<AuthenticateResult> HandleAuthenticateAsync() =>
        return tokenDecryptor.Decrypt(this);
}

...

services.AddAuthentication("Scheme")
    .AddScheme<AuthenticationSchemeOptions, AuthHandler>("Scheme", options => { });

Current solution is to manually cross-wire application service which is not quite convenient:

services.AddTransient(provider => container.GetInstance<ITokenDecryptor>());

Solution

  • Tao's answer is right. The easiest way to implement this is to cross wire the AuthHandler to Simple Injector.

    This can be done as follows:

    // Your original configuration:
    services.AddAuthentication("Scheme")
        .AddScheme<AuthenticationSchemeOptions, AuthHandler>("Scheme", options => { });
    
    // Cross wire AuthHandler; let Simple Injector create AuthHandler.
    // Note: this must be done after the call to AddScheme. Otherwise it will
    // be overridden by ASP.NET.
    services.AddTransient(c => container.GetInstance<AuthHandler>());
    
    // Register the handler with its dependencies (in your case ITokenDecryptor) with 
    // Simple Injector
    container.Register<AuthHandler>();
    container.Register<ITokenDecryptor, MyAwesomeTokenDecryptor>(Lifestyle.Singleton);