Skip to main content
Version: v1.2.0

Authentication with shared access keys

The Arcus.WebApi.Security package provides a mechanism that uses shared access keys to grant access to a web application. This authentication process consists of two parts:

  1. Find the configured parameter that holds the shared access key, this can be a request header, a query parameter or both.
  2. Shared access key matches the value with the secret stored, determined via configured secret provider

Installation

This feature requires to install our NuGet package

PM > Install-Package Arcus.WebApi.Security

Globally enforce shared access key authentication

Introduction

The SharedAccessKeyAuthenticationFilter can be added to the request filters in an ASP.NET Core application. This filter will then add authentication to all endpoints via a shared access key configurable on the filter itself.

Usage

The authentication requires an ICachedSecretProvider or ISecretProvider dependency to be registered with the services container of the ASP.NET request pipeline. This is typically done in the ConfigureServices method of the Startup class. Once this is done, the SharedAccessKeyAuthenticationFilter can be added to the filters that will be applied to all actions:

using Arcus.Security.Core.Caching;
using Arcus.WebApi.Security.Authentication.SharedAccessKey;
using Microsoft.Extensions.DependencyInjection;

public class Startup
{
public void ConfigureServices(IServiceCollections services)
{
services.AddSingleton<ICachedSecretProvider>(serviceProvider => new MyCachedSecretProvider());
services.AddMvc(options => options.Filters.Add(new SharedAccessKeyAuthenticationFilter(headerName: "http-request-header-name", queryParameterName: "api-key", secretName: "shared-access-key-name")));
}
}

Enforce shared access key authentication per controller or operation

Introduction

The SharedAccessKeyAuthenticationAttribute can be added on both controller- and operation level in an ASP.NET Core application. The shared access key authentication will then be applied to the endpoint(s) that are decorated with the SharedAccessKeyAuthenticationAttribute.

Usage

The authentication requires an ICachedSecretProvider or ISecretProvider dependency to be registered with the services container of the ASP.NET request pipeline. This is typically done in the ConfigureServices method of the Startup class:

using Arcus.Security.Core.Caching;
using Microsoft.Extensions.DependencyInjection;

public class Startup
{
public void ConfigureServices(IServiceCollections services)
{
services.AddSingleton<ICachedSecretProvider>(serviceProvider => new CachedSecretProvider(new MySecretProvider()));
services.AddMvc();
}
}

After that, the SharedAccessKeyAuthenticationAttribute attribute can be applied on the controllers, or if more fine-grained control is needed, on the operations that requires authentication:

using Arcus.WebApi.Security.Authentication.SharedAccessKey;

[ApiController]
[SharedAccessKeyAuthentication(headerName: "http-request-header-name", queryParameterName: "api-key", secretName: "shared-access-key-name")]
public class MyApiController : ControllerBase
{
[HttpGet]
[Route("authz/shared-access-key")]
public Task<IActionResult> AuthorizedGet()
{
return Task.FromResult<IActionResult>(Ok());
}
}

Behavior in validating shared access key parameter

The package supports different scenarios for specifying the shared access key parameter and is supported for global or per controller/operation use cases.

  • Use header only - Only the specified request header will be validated for the shared access key, any supplied query parameter will not be taken into account.
using Arcus.Security.Core.Caching;
using Arcus.WebApi.Security.Authentication.SharedAccessKey;
using Microsoft.Extensions.DependencyInjection;

public class Startup
{
public void ConfigureServices(IServiceCollections services)
{
services.AddSingleton<ICachedSecretProvider>(serviceProvider => new MyCachedSecretProvider());
services.AddMvc(options => options.Filters.Add(new SharedAccessKeyAuthenticationFilter(headerName: "http-request-header-name", secretName: "shared-access-key-name")));
}
}

  • Use query parameter only - Only the specified query parameter will be validated for the shared access key, any supplied request header will not be taken into account.
using Arcus.Security.Core.Caching;
using Arcus.WebApi.Security.Authentication.SharedAccessKey;
using Microsoft.Extensions.DependencyInjection;

public class Startup
{
public void ConfigureServices(IServiceCollections services)
{
services.AddSingleton<ICachedSecretProvider>(serviceProvider => new MyCachedSecretProvider());
services.AddMvc(options => options.Filters.Add(new SharedAccessKeyAuthenticationFilter(queryParameterName: "api-key", secretName: "shared-access-key-name")));
}
}

  • Support both header & query parameter - Both the specified request header and query parameter will be validated for the shared access key.
using Arcus.Security.Core.Caching;
using Arcus.WebApi.Security.Authentication.SharedAccessKey;
using Microsoft.Extensions.DepdendencyInjection;

public class Startup
{
public void ConfigureServices(IServiceCollections services)
{
services.AddSingleton<ICachedSecretProvider>(serviceProvider => new MyCachedSecretProvider());
services.AddMvc(options => options.Filters.Add(new SharedAccessKeyAuthenticationFilter(headerName: "http-request-header-name", queryParameterName: "api-key", secretName: "shared-access-key-name")));
}
}

If both header and query parameter are specified, they must both be valid or an Unauthorized will be returned.


Bypassing authentication

The package supports a way to bypass the shared access key authentication for certain endpoints. This works with adding one of these attributes to the respectively endpoint:

  • BypassSharedAccessKeyAuthentication
  • AllowAnonymous

Works on both method and controller level, using either the shared access key filter or attribute.

using Arcus.WebApi.Security.Authentication.SharedAccessKey;

[ApiController]
[SharedAccessKeyAuthentication("MySecret", "MyHeader")]
public class SystemController : ControllerBase
{
[HttpGet('api/v1/health')]
[BypassSharedAccessKeyAuthentication]
public IActionResult GetHealth()
{
return Ok();
}
}

← back