MNW #022: How To Implement API Key Authentication In ASP.NET Core

Jan 28 2023

5 min read

I wanted to take this opportunity to share how I can help you be a better .NET engineer:

On my Patreon community page I share all of the source code that I use in my YouTube videos. So if you want to gain access to the source code, and also to be able to ask me any questions you may have, you can do that by supporting me on Patreon.

I split the code for every video into a before and after version, so you can pick up from the start and code along with me in the video. Or just grab the final version of the code, if you want to.


In this week's newsletter I want to show you how to implement API Key authentication in ASP.NET Core. This authentication approach uses an API Key to authenticate the client of an API. You can pass the API Key to the API in a few ways, such as through the query string or a request header.

I will show you how to implement API Key authentication where the API key is passed in a request header. But the implementation would be similar if we were to use any other approach.

When would you want to use API Key authentication? This kind of authentication mechanism is common in Server-to-Server (S2S) communication. When your API serves request for other server-side applications to consume and integrate with. It's less common in client-server communication scenarios.

Let's see how we can implement API Key authentication in ASP.NET Core.

Implementing API Key Authentication

We will start off by creating an attribute that we can place on endpoints where we want to apply API Key authentication. It won't be any kind of attribute, because we will use a ServiceFilterAttribute.

What a ServiceFilterAttribute allows us to do is specify a type for the filter that will be created for that attribute. This means we can implement our authentication logic in an IAuthorizationFilter. With a ServiceFilterAttribute we also have support for dependency injection in our IAuthorizationFilter implementation.

Let's first define the ApiKeyAttribute class:

public class ApiKeyAttribute : ServiceFilterAttribute
{
    public ApiKeyAttribute()
        : base(typeof(ApiKeyAuthorizationFilter))
    {
    }
}

In the ApiKeyAttribute we specify ApiKeyAuthorizationFilter class as the filter that will be resolved from the DI container. Here's what it looks like:

public class ApiKeyAuthorizationFilter : IAuthorizationFilter
{
    private const string ApiKeyHeaderName = "X-API-Key";

    private readonly IApiKeyValidator _apiKeyValidator;

    public ApiKeyAuthorizationFilter(IApiKeyValidator apiKeyValidator)
    {
        _apiKeyValidator = apiKeyValidator;
    }

    public void OnAuthorization(AuthorizationFilterContext context)
    {
        string apiKey = context.HttpContext.Request.Headers[ApiKeyHeaderName];

        if (!_apiKeyValidator.IsValid(apiKey))
        {
            context.Result = new UnauthorizedResult();
        }
    }
}

The implementation comes down to validating the API Key obtained from the header of the current request. If we determine that the API Key is not valid, we set the value of AuthorizationFilterContext.Result to a new instance of an UnauthorizedResult.

And lastly, all that's left for us to do is implement our custom validation logic for the API Key inside of ApiKeyValidator:

public class ApiKeyValidator : IApiKeyValidator
{
    public bool IsValid(string apiKey)
    {
        // Implement logic for validating the API key.
    }
}

public interface IApiKeyValidator
{
    bool IsValid(string apiKey);
}

The actual implementation for validating the API Key will vary based on your use case, and where you are storing the API keys. For example, if you store the API keys in the database you would check if the provided API Key exists in the database. If it exists, then validation passes. If it doesn't exist, then validation fails and we return an UnauthorizedResult.

Registering Services With Dependency Injection

We have to make sure to register our ApiKeyAuthorizationFilter and ApiKeyValidator services with the dependency injection container.

builder.Services.AddSingleton<ApiKeyAuthorizationFilter>();

builder.Services.AddSingleton<IApiKeyValidator, ApiKeyValidator>();

This will register them as singleton services in our application. You can use a different service scope such as Transient or Scoped if you need to.

Applying API Key Authentication To Endpoints

Finally, with our API Key authentication in place, we can apply the ApiKeyAttribute attribute to our endpoints:

public class NewslettersController : ControllerBase
{
    [ApiKey]
    [HttpGet]
    public IActionResult Get()
    {
        // ...
    }
}

In this case I'm applying the ApiKeyAttribute to an endpoint, but you can also apply it on the NewslettersController and it will add authentication to all the endpoints for that controller.

Next Steps

Now that you know how to implement API Key authentication, I think you should also learn how to implement JWT authentication. And while you're at it, why not throw authorization into the mix.

I made a few videos about JWT authentication and permission authorization that you should take a look at next:


Whenever you're ready, there are 3 ways I can help you 🔥

  1. To access all of the source code that I use in my YouTube videos support me on Patreon
  2. For more practical & in-depth coding examples subscribe to my YouTube channel
  3. Promote yourself to 11k+ subscribers by sponsoring this newsletter (booked out 2 months)

Special Offers 📢

About the Newsletter

11k+ subscribers get one tip to improve their software engineering and .NET skills every Saturday morning.

Connect with Me

Join 11,774 .NET engineers getting 1 actionable .NET tip every Saturday

Actionable tips

Easy to implement

5 minute read

Free, forever