I am trying to find a way to inject a dependency in Startup.cs, for a aspnet5 application. I am aware of the following previous question, but hopefully I can expand on my particular requirements:
Aspnet core 5.0 inject dependency in startup.cs constructor
I initially needed a way to fire a custom method after OnSignIn with MS Identity Platform (IP) within my app. After posting the following questions, I was quickly pointed in the right direction:
How to fire a custom method after OnSignIn with MS Identity Platform
In short, during ConfigureServices in StartUp.cs, I needed to configure the IP middleware service, to add my own methods to some of its available events. Works a treat!
So I initially tried:
services.Configure<OpenIdConnectOptions>(OpenIdConnectDefaults.AuthenticationScheme, options =>
options.Events = new OpenIdConnectEvents
{
OnTicketReceived = async ctex =>
{
// Blah
},
});
As I say, this works great. However, to do anything serious, I need access to my existing code and the DI magic that goes with it. This is where I a hitting this problem. I need my custom logic that requires DI, during ConfigureServices, before I have configured the services for DI.
On the same post, someone pointed out that you can wrap up the configuration, and essentially inject it back in, so you can get DI back. Great! But for some reason, I can only inject the handler, either as a Singleton, or Transient. Not Scoped. I get to some extent why it can't be scoped (if it is has a dependency of its own on a transient service), but then are why both extremes ok? Why is Singleton OK? Why is Transient? It just so happens, but my DI requirements are that I would need to inject scoped services, as that is what I need. I need some of the data to persist across instances, but I can't have a single instances shared across the whole application/user base.
So then I tried:
public class AzureAdOpendIdHandler : IConfigureNamedOptions<OpenIdConnectOptions>
{
public AzureAdOpendIdHandler(Authentication.AuthenticationManager authenticationManager)
{
AuthenticationManager = authenticationManager;
}
public Authentication.AuthenticationManager AuthenticationManager { get; }
public void Configure(string name, OpenIdConnectOptions options)
{
options.Events = new OpenIdConnectEvents
{
OnTicketReceived = context =>
{
//Blah
return Task.CompletedTask;
},
};
}
}
Then called in StartUp.cs like:
services.AddScoped<Authentication.IAuthenticationManager, Authentication.AuthenticationManager>();
services.AddSingleton<IConfigureOptions<OpenIdConnectOptions>, AzureAdOpendIdHandler>();
Again, the handler works fine, and everything fires, as long as I don't try and pass "AuthenticationManager" within the constructor. I get an error saying that I can't inject a scoped service into a singleton service.
I keep getting within spitting distance of doing what I need, but there is always another block in the way.
In summary:
- To override/extend MS Identity Platform, I need to make changes in ConfigureServices() in StartUp.cs
- These changes require my classes to be available via DI.
- The DI must allow me to pass them as scoped
So far, I can only meet the first two requirements, I can not find a way to satisfy all three.
My end requirement is to be able to add a call to my AuthenticationManager class from within the following OnTicketReceived Event:
services.Configure<OpenIdConnectOptions>(OpenIdConnectDefaults.AuthenticationScheme, options =>
options.Events = new OpenIdConnectEvents
{
OnTicketReceived = async ctex =>
{
//use my AuthenticationManager class!!
},
});
I have tried the direct method, wrapping things up in a handler and injecting, but DI seems to be getting in the way now.
Any help, would be gratefully received.