Closed
Description
Hi,
Thanks for creating this library. I was testing the library and came across the following.
I am trying to add a second schema but due to a registration issue in the ApiKeyExtension the second provider overrides the first provider.
services.AddAuthentication(ApiKeyDefaults.AuthenticationScheme)
.AddApiKeyInHeader<ProviderOne>(options =>
{
options.Realm = "Realm 1";
options.KeyName = "X-API-KEY";
})
.AddApiKeyInHeader<ProviderTwo>("SCHEMA2", options =>
{
options.Realm = "Realm 2";
options.KeyName = "X-API-KEY";
});
private static AuthenticationBuilder AddApiKey<TApiKeyProvider, TApiKeyHandler>(this AuthenticationBuilder builder, string authenticationScheme, string displayName, Action<ApiKeyOptions> configureOptions)
where TApiKeyProvider : class, IApiKeyProvider
where TApiKeyHandler : AuthenticationHandler<ApiKeyOptions>
{
// Adds implementation of IApiKeyProvider to the dependency container.
builder.Services.AddTransient<IApiKeyProvider, TApiKeyProvider>(); //I think that this overrides the registration make
builder.Services.Configure<ApiKeyOptions>(
authenticationScheme,
o => o.ApiKeyProviderType = typeof(TApiKeyProvider)
);
// Adds post configure options to the pipeline.
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<ApiKeyOptions>, ApiKeyPostConfigureOptions>());
// Adds api key authentication scheme to the pipeline.
return builder.AddScheme<ApiKeyOptions, TApiKeyHandler>(authenticationScheme, displayName, configureOptions);
}
This will cause ApiKeyHandlerBase:L193 to always return a instance to return. This will prevent it from reaching if (apiKeyProvider == null)
and resolving a provider based on the type in the options
apiKeyProvider = Context.RequestServices.GetService(Options.ApiKeyProviderType) as IApiKeyProvider;
private async Task<IApiKey> ValidateUsingApiKeyProviderAsync(string apiKey)
{
var apiKeyProvider = Context.RequestServices.GetService<IApiKeyProvider>();
if (apiKeyProvider == null)
{
if (Options.ApiKeyProviderType != null)
{
apiKeyProvider = Context.RequestServices.GetService(Options.ApiKeyProviderType) as IApiKeyProvider;
}
if (apiKeyProvider == null)
{
throw new InvalidOperationException($"Either {nameof(Options.Events.OnValidateKey)} delegate on configure options {nameof(Options.Events)} should be set or an implementaion of {nameof(IApiKeyProvider)} should be registered in the dependency container.");
}
}
return await apiKeyProvider.ProvideAsync(apiKey).ConfigureAwait(false);
}
Metadata
Metadata
Assignees
Labels
No labels