I'm trying to set up a custom authentication scheme in ASP.NET Core 8. I have created AuthenticationOptions and an AuthenticationHandler.
However the issue happens on startup, the line where options are configured is apparently never reached.
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = ApiKeyAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = ApiKeyAuthenticationDefaults.AuthenticationScheme;
})
.AddScheme<ApiKeyAuthenticationOptions, ApiKeyAuthenticationHandler>(ApiKeyAuthenticationDefaults.AuthenticationScheme, options =>
{
options.ApiKey = configuration["ApiKey"] ?? throw new Exception("No API key was configured");
});
I'm sure it is not executing because if I put a breakpoint on that line it is never hit and if ApiKey
is null the exception on the right side of the null coalescing operator is not thrown.
namespace API.Authentication.ApiKeyAuthenticaiton
{
public class ApiKeyAuthenticationHandler : AuthenticationHandler<ApiKeyAuthenticationOptions>
{
public ApiKeyAuthenticationHandler(IOptionsMonitor<ApiKeyAuthenticationOptions> options,
ILoggerFactory logger,
UrlEncoder encoder) : base(options, logger, encoder)
{
ApiKeyAuthenticationOptions opts = options.CurrentValue;
if (opts.ApiKey == null) throw new ArgumentNullException(nameof(opts.ApiKey));
}
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
// Validate API key
if (!Request.Headers.TryGetValue("x-api-key", out var key)) return AuthenticateResult.Fail("Missing API key");
if (key != Options.ApiKey) return AuthenticateResult.Fail("Invalid API key");
return AuthenticateResult.Success(new AuthenticationTicket(new ClaimsPrincipal(), Scheme.Name));
}
}
}
public class ApiKeyAuthenticationOptions : AuthenticationSchemeOptions
{
public string ApiKey { get; set; } = null!;
}
According to this issue
The AuthenticationHandler constructor doesn't initialize Options because it doesn't have the scheme name yet. It's initialized after the authentication middleware calls InitializeAsync.