C# Web API client Authentication with X-API-KEY

The Web API can authenticate the client through an API key with a middleware or an action filter.

Here’s how you can implement a middleware that does that:

public class ApiKeyMiddleware
{
    private readonly RequestDelegate _next;
    private const string ApiKeyHeaderName = "X-API-KEY";

    public ApiKeyMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        if (!context.Request.Headers.TryGetValue(ApiKeyHeaderName, out var potentialApiKey))
        {
            context.Response.StatusCode = StatusCodes.Status401Unauthorized;
            await context.Response.WriteAsync("Unauthorized");
            return;
        }

        var configuration = context.RequestServices.GetRequiredService<IConfiguration>();
        var validApiKey = configuration.GetValue<string>("ApiKey");

        if (potentialApiKey != validApiKey)
        {
            context.Response.StatusCode = StatusCodes.Status403Forbidden;
            await context.Response.WriteAsync("Forbidden");
            return;
        }

        await _next(context);
    }
}

This middleware checks each incoming request for an "X-API-KEY" header. If the header is absent or the key is invalid, it rejects the request with an HTTP 401 or 403 status.

You can use this middleware in your Startup.cs like this:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // ...

    app.UseMiddleware<ApiKeyMiddleware>();

    // ...
}

In appsettings.json:

{
    "ApiKey": "your-valid-api-key",
    // ...
}

To Add ApiKey in Swagger:

public void ConfigureServices(IServiceCollection services)
{
    // ... other services

    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new OpenApiInfo { Title = "Your API", Version = "v1" });

        // Define the BearerAuth scheme
        c.AddSecurityDefinition("BearerAuth", new OpenApiSecurityScheme
        {
            Description = "Input your Bearer token in the following format - Bearer {your token here}",
            Name = "Authorization",
            In = ParameterLocation.Header,
            Type = SecuritySchemeType.ApiKey,
            Scheme = "BearerAuth"
        });

        c.AddSecurityRequirement(new OpenApiSecurityRequirement
        {
            {
                new OpenApiSecurityScheme
                {
                    Reference = new OpenApiReference
                    {
                        Type = ReferenceType.SecurityScheme,
                        Id = "BearerAuth"
                    },
                    Scheme = "oauth2",
                    Name = "BearerAuth",
                    In = ParameterLocation.Header
                },
                new List<string>()
            }
        });
    });
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // ... other middleware

    app.UseSwagger();
    app.UseSwaggerUI(c =>
    {
        c.SwaggerEndpoint("/swagger/v1/swagger.json", "Your API V1");
        c.RoutePrefix = string.Empty;
    });
}

In order to receive other custom headers like X-UserName:

public class UserNameMiddleware
{
    private readonly RequestDelegate _next;
    private const string UserNameHeaderName = "X-AUTH-USERNAME";

    public UserNameMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        if (context.Request.Headers.TryGetValue(UserNameHeaderName, out var userName))
        {
            context.Items[UserNameHeaderName] = userName.ToString();
        }

        await _next(context);
    }
}

And then, in startup.cs

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // ...

    app.UseMiddleware<UserNameMiddleware>();

    // ...
}