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:
- Find the configured parameter that holds the shared access key, this can be a request header, a query parameter or both.
- 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
We created a SharedAccessKeyAuthenticationFilter
MVC filter which will be applied to all actions:
using Arcus.WebApi.Security.Authentication.SharedAccessKey;
using Microsoft.Extensions.DependencyInjection;
public class Startup
{
public void ConfigureServices(IServiceCollections services)
{
// See https://security.arcus-azure.net/features/secret-store/ for more information.
services.AddSecretStore(stores => stores.AddAzureKeyVaultWithManagedIdentity("https://your-keyvault.vault.azure.net/", CacheConfiguration.Default));
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
We created an SharedAccessKeyAuthenticationAttribute
attribute which can be applied on the controllers, or if more fine-grained control is needed, on the operations that requires authentication:
using Microsoft.Extensions.DependencyInjection;
public class Startup
{
public void ConfigureServices(IServiceCollections services)
{
// See https://security.arcus-azure.net/features/secret-store/ for more information.
services.AddSecretStore(stores => stores.AddAzureKeyVaultWithManagedIdentity("https://your-keyvault.vault.azure.net/", CacheConfiguration.Default));
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());
}
}
For this setup to work, an Arcus secret store is required as the provided secret name (in this case "shared-access-key-name"
) will be looked up.
See our offical documentation for more information about setting this up.
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.WebApi.Security.Authentication.SharedAccessKey;
using Microsoft.Extensions.DependencyInjection;
public class Startup
{
public void ConfigureServices(IServiceCollections services)
{
// See https://security.arcus-azure.net/features/secret-store/ for more information.
services.AddSecretStore(stores => stores.AddAzureKeyVaultWithManagedIdentity("https://your-keyvault.vault.azure.net/", CacheConfiguration.Default));
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.WebApi.Security.Authentication.SharedAccessKey;
using Microsoft.Extensions.DependencyInjection;
public class Startup
{
public void ConfigureServices(IServiceCollections services)
{
// See https://security.arcus-azure.net/features/secret-store/ for more information.
services.AddSecretStore(stores => stores.AddAzureKeyVaultWithManagedIdentity("https://your-keyvault.vault.azure.net/", CacheConfiguration.Default));
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.WebApi.Security.Authentication.SharedAccessKey;
using Microsoft.Extensions.DependencyInjection;
public class Startup
{
public void ConfigureServices(IServiceCollections services)
{
// See https://security.arcus-azure.net/features/secret-store/ for more information.
services.AddSecretStore(stores => stores.AddAzureKeyVaultWithManagedIdentity("https://your-keyvault.vault.azure.net/", CacheConfiguration.Default));
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();
}
}