First off, sorry for the really bad question title. I couldn’t think of a better way to word it. I’m open to suggestions for an edit!
In my ASP.NET app written to target .NET 7, I have this in my Program.cs class:
var builder = WebApplication.CreateBuilder(args);
builder.Services.Configure<AppConfiguration>(builder.Configuration.GetSection(AppConfiguration.ConfigurationSectionName));
builder.Services.AddAuthentication(options =>
{
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
}
)
.AddOpenIdConnect(options =>
{
options.ClientId = "whatever";
// etc...
options.Events = new OpenIdConnectEvents()
{
OnRemoteFailure = AuthenticationHelper.OnAuthenticationFailed,
OnAuthorizationCodeReceived = AuthenticationHelper.OnAuthenticationSucceeded
};
});
Then I have my AuthenticationHelper class which, at the moment (I need to build it out) looks like this:
internal static class AuthenticationHelper
{
internal static Task OnAuthenticationFailed(RemoteFailureContext context)
{
context.HandleResponse();
context.Response.Redirect("/?errormessage=" + context.Failure?.Message ?? string.Empty);
return Task.FromResult(0);
}
internal static Task OnAuthenticationSucceeded(AuthorizationCodeReceivedContext context)
{
var claim = new Claim(_appConfiguration.MyClaimName, "My value");
return Task.FromResult(0);
}
}
Note that second-to-last line, where I’m referencing a variable named _appConfiguration
. That obviously doesn’t work because the variable isn’t declared anywhere. I’ve copied this line from another class where dependency injection is used to inject the app configuration.
The problem is that I obviously can’t use DI in my AuthenticationHelper class becaues it’s a static
class, and, so far, I can’t work out how to change it to a standard class (i.e. not static
) and still be able to reference it when assigning values to OnRemoteFailure
and OnAuthorizationCodeReceived
in Program.cs.
As far as I can see, my two options are to either:
- Find another way to get the app configuration in Authentication Helper without using DI.
- Find a way to reference an instance of AuthenticationHelper in Program.cs if I make it non-static.
So far, I can’t figure out how to do either! The closest I’ve come is to make the AuthenticationHelper class non-static, add it as a singleton service in Program.cs, and change the event option assignments to e.g.:
OnAuthorizationCodeReceived = builder.Services.BuildServiceProvider().GetService<IAuthenticationHelper>().OnAuthenticationSucceeded
This works, but I’m aware that using BuildServiceProvider()
is a bad idea, as it creates a new instance of the singleon class every time.
What’s the best approach to this?
2
Answers
Register
AppConfiguration
as DI service and access it using the context object like this:If
AuthenticationHelper
needs to be static, Method Injection is the generally the answer.This means that, in your case, you add
AppConfiguration
as parameter to theOnAuthenticationSucceeded
method, as shown here:Inside your Composition Root you then supply
AppConfiguration
to theOnAuthenticationSucceeded
method, as demonstrated next: