'AddScheme options not loading from appsettings
I have this line in program.cs
builder.Services.AddAuthentication()
.AddScheme<SharedSecretAuthenticationOptions, SharedSecretAuthenticationHandler>(SharedSecretScheme, null);
The option class looks like this:
public class SharedSecretAuthenticationOptions : AuthenticationSchemeOptions
{
public string? Secret { get; set; }
}
and in appsettings.json I have:
"SharedSecret": {
"Secret": "Test"
}
The handler in part looks like this:
public class SharedSecretAuthenticationHandler : AuthenticationHandler<SharedSecretAuthenticationOptions>
{
public SharedSecretAuthenticationHandler(IOptionsMonitor<SharedSecretAuthenticationOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
: base(options, logger, encoder, clock)
{
}
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
{
string? secret = Options.Secret;
// Do secret sauce here.
}
}
I'm expecting secret to be "Test" as per settings but its null. I wondered what I was missing?
(Note if I default Secret to "Test" in code then all works, just doesn't want to read it from settings).
Sniffing around the asp.net core source code shows AddScheme calling AddOptions so I thought that would do. In the end I got it working by adding
IConfigurationSection? dbSection = builder.Configuration.GetSection(SharedSecretScheme);
builder.Services.AddOptions<SharedSecretAuthenticationOptions>(SharedSecretScheme).Bind(dbSection);
However I can't shake the feeling I'm missing something, or there is more "automatic" way for options to bind in the settings?
Update
An answer below suggests including IConfiguration
in the handler constructor and accessing the setting directly. Even if that works it is quite undesirable to bypass the use of IOptionsMonitor
Solution 1:[1]
Have you tried these codes?
public class SharedSecretAuthenticationHandler : AuthenticationHandler<SharedSecretAuthenticationOptions>
{
private readonly IConfiguration _configuration;
public SharedSecretAuthenticationHandler(IOptionsMonitor<SharedSecretAuthenticationOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, IConfiguration configuration)
: base(options, logger, encoder, clock)
{
_configuration = configuration;
}
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
{
string? secret = _configuration["SharedSecret:Secret"];
return Task.FromResult(AuthenticateResult.Fail("Invalid username or password"));
// Do secret sauce here.
}
}
my codes in program.cs:
builder.Services.AddAuthentication("Basic")
.AddScheme<SharedSecretAuthenticationOptions, SharedSecretAuthenticationHandler>("Basic", null);
appsetting.json:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"SharedSecret": {
"Secret": "Test"
}
}
Update?
Acrroding to your comment,I modified my codes in program.cs:
IConfigurationSection? dbSection = builder.Configuration.GetSection("SharedSecret:Secret");
builder.Services.AddAuthentication("Basic")
.AddScheme<SharedSecretAuthenticationOptions, SharedSecretAuthenticationHandler>("Basic",x=>x.Secret= dbSection.Value);
I suppose that you did not set the Options when you use AddScheme method,So the value of Secret was null
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |