Thursday 12 November 2020

ASP.NET CORE security authentication whit api key

Security authentication

Today every api need to secure the input request from public access. This is the first part of couple posts to secure your api end point.


What is api key authentication

Api key is public key that was given to the client from the api owners.


What we need to integrate web api security in c#

  • Filter
We need to handle every incoming request and check for api key in header, if the key is valid the request will continue, otherwise the error will be throw
public class ApiKeyFilter : IActionFilter
{
    private readonly MyContext _context;

    public ApiKeyFilter(MyContext context)
    {
        _context = context;
    }

    public void OnActionExecuting(ActionExecutingContext ae_context)
    {
        string apiKey = ae_context.HttpContext.Request.Headers["api_key"];

        ApiKeyModel model = _context.api_key.Where(x => x.api_key.Equals(apiKey)).FirstOrDefault();
        if (model == null)
        {
            ae_context.Result = new JsonResult("api key not exists");
            return;
        }
        if (model.date < DateTime.Now)
        {
            ae_context.Result = new JsonResult("api key expired");
            return;
        }
    }

    public void OnActionExecuted(ActionExecutedContext context) { }
}
After creating the filter we need to tell the api to listen for that filter
Project > startup.cs
public void ConfigureServices(IServiceCollection services)
{
    ... 
    // global level scope
    // services.AddMvc(opts => { opts.Filters.Add(new ApiKeyFilter()); });
    // not on global level scope, can be used on some controllers
    services.AddScoped<ApiKeyFilter>();
    ... 

We have 2 options, add the filter on global scope (this will trigger the protection on every call) or on non global level (we can add protection to specific controllers or method). You can use what ever suet your needs better.

Authenticate for controller

[ServiceFilter(typeof(ApiKeyFilter))]
[ApiController]
public class MainApiController : ControllerBase
{
   ...
}

  • SQL table
This table will hold our public api keys and was reached via Microsoft.EntityFrameworkCore (if you need more info write a comment below)
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[api_key](
[id] [bigint] IDENTITY(1,1) NOT NULL,
[api_key] [varchar](255) NULL,
[app_name] [varchar](255) NULL,
[date] [datetime] NULL,
[status] [bit] NULL,
 CONSTRAINT [PK_api_key] PRIMARY KEY CLUSTERED 
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO

And there you go, if you make request to your protected api you should see "api key not exists" exception.

Add some keys to your table and make the request again but this time add api_key to your header whit the key value and you should get the data response.

In next chapter we will integrate Digital Signing whit private and public key protection, also we will integrate and user jwt bearer token authentication. Whit all of this 3 methods your api will be unbreakable.

Happy coding...

No comments:

Post a Comment