ASP.NET Core, C#, WebApi

Securing ASP.NET Core WebApi with an API Key

2 min read

I read the article from Aram Tchekrekjian, which he goes in great length about techniques to secure a Web API, that is, using a Middleware and using an attribute that uses the IAsyncActionFilter. I would like to add another technique to this list using also an attribute, but one that uses the IAsyncAuthorizationFilter instead. This filter is called earlier in the chain of filters and can stop early a bad request using an invalid API Key. To learn more about filters, check out the documentation.

I will use the starter ASP.NET Core 3 API template that comes with dotnet. You can create it through Visual Studio or using the command line dotnet new webapi <ProjectName>.

In my scenario, I will use a combination of Client Id/Api Key.

Setup

At the root of the project, create 2 folders that will host the files:

  • Attributes
  • Filters

In the Attributes folder, create a class file named ApiKeyAuthorizeAttribute. In the Filters folder, create a class file named ApiKeyAuthorizeAsyncFilter. Your solution should look like this

solution structure

Open the ApiKeyAuthorizeAttribute class file. Decorate the class with the following AttributeUsage

This will determine how the attribute class can be used. The attribute can be applied on a class, in this case the controller, or on a method, in this case the method that can handle a route.

The class should also derive from the TypeFilterAttribute. Your class should look like this:

Now for the ApiKeyAuthorizeAsyncFilter class, it should implement the IAsyncAuthorizationFilter interface.

This interface gives us access to a method Task OnAuthorizationAsync(AuthorizationFilterContext context) and it’s in this method that we will verify the API Key associated to a client. Since this is a filter, it will be registered in the DI, and thus give us access to all the DI goodies.

To validate the api key, I created an ApiKeyService class that handles the logic to verify if I’m authorized or not. My implementation class implement an interface that can have the following shape:

Now I can implement the logic in my filter. Since I have access to the context, I have access to the request, and so I can extract the information I need to validate. My implementation looks like this:

Don’t forget to register your IApiKeyService implementation in your Startup.ConfigureServices method:

Once I have implemented my filter, it’s time to add it to my controller. In the controller class WeatherForecastController, decorate it with [ApiKeyAuthorize].

Test

Using postman, I execute a GET request to https://localhost:5001/WeatherForecast. I don’t put any Headers for my Client Id or my Api Key. I get a 401.

no headers unauthorized

If I put the ApiKey header, but not the ClientId header, it will also trigger a 401 unauthorized because the ClientId header is missing

apikey header no clientid header unauthorized

If the combination of the api key and the client id is wrong, it will also tell me I’m not authorized

apikey combination wrong unauthorized

Now if I put the right combination, I will get access and a 200

successful combination authorized

Things not to forget

You should think about a caching mechanism for the api key/client id combination as you don’t want to hit your underlying data store to validate those for every request. It will become expensive.