Reputation: 2002
I have a Web API project that has a number of endpoints that are protected using an API key. To achieve this I have written some middleware to handle checking the header for the API key and validating it. This middleware is configured in the Startup.cs
app.UseMiddleware<ApiKeyMiddleware>();
This works perfectly, however I now have the requirement to have one endpoint that does not require any authorisation so it can be viewed in browser. I was hoping this would be done by using the AllowAnonymous
attribute, however the middleware still checks for the API key.
I can achieve what I want by removing the middleware and making the API key check into an attribute, but is there a better way to do this?
EDIT:
This is the API key middleware implementation.
public class ApiKeyMiddleware
{
private readonly RequestDelegate _next;
private const string API_KEY_HEADER = "z-api-key";
public ApiKeyMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
if (!context.Request.Headers.TryGetValue(API_KEY_HEADER, out var extractedApiKey))
{
context.Response.StatusCode = 401;
await context.Response.WriteAsync($"Api Key was not found in request. Please pass key in {API_KEY_HEADEr} header.");
return;
}
var appSettings = context.RequestServices.GetRequiredService<IConfiguration>();
var validApiKey = appSettings.GetValue<string>(API_KEY_HEADER);
if (validApiKey != extractedApiKey)
{
context.Response.StatusCode = 401;
await context.Response.WriteAsync("Invalid api key.");
return;
}
await _next(context);
}
}
Upvotes: 4
Views: 2701
Reputation: 156
you can use HttpContext
object to access endpoint and metadata like attributes.
var endpoint = context.GetEndpoint();
var isAllowAnonymous = endpoint?.Metadata.Any(x => x.GetType() == typeof(AllowAnonymousAttribute));
then add a conditional in your check to skip.
if (isAllowAnonymous == true)
{
await _next(context);
return;
}
Note: you should place your middleware after Routing
middleware to use GetEndpoint
extension method. if your middleware place before Routing
middleware
GetEndpoint
extension method return null
app.UseRouting();
app.UseMiddleware<ApiKeyMiddleware>();
Upvotes: 8