It seems like you are looking for a global filter in this specific case.
An authentication filter is a component that authenticates an HTTP request
You would basically send the shared / static api key with every request in the Authorization header and the custom filter would process this and decide whether the request is valid or not.
A basic implementation of the filter:
public class ApiKeyAuthenticationAttribute : IAuthenticationFilter
{
public bool AllowMultiple { get; set; }
public async Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
{
HttpRequestMessage request = context.Request;
// Get Auth header
AuthenticationHeaderValue authorization = request.Headers.Authorization;
// Validate the static token
if (authorization?.Parameter == "123")
{
IPrincipal principal = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim> { new Claim("CLAIMTYPE", "CLAIMVALUE") }));
context.Principal = principal;
}
else
{
context.ErrorResult = new AuthenticationFailureResult(request);
}
}
public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)
{
var challenge = new AuthenticationHeaderValue("Basic");
context.Result = new AddChallengeOnUnauthorizedResult(challenge, context.Result);
return Task.FromResult(0);
}
}
And to enable it for all calls to your api add it to your WebApiConfig:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Some more config here
config.Filters.Add(new IdentityBasicAuthenticationAttribute());
}
}
The AuthenticationFailureResult and AddChallengeOnUnauthorizedResult are implementations of IHttpActionResult. For comprehensiveness I will add them here.
AuthenticationFailureResult
class AuthenticationFailureResult : IHttpActionResult
{
private HttpRequestMessage _request;
public AuthenticationFailureResult(HttpRequestMessage request)
{
_request = request;
}
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
response.RequestMessage = _request;
response.Content = new StringContent("ACCESS DENIED MESSAGE");
return Task.FromResult(response);
}
}
AddChallengeOnUnauthorizedResult
class AddChallengeOnUnauthorizedResult : IHttpActionResult
{
public AddChallengeOnUnauthorizedResult(AuthenticationHeaderValue challenge, IHttpActionResult innerResult)
{
Challenge = challenge;
InnerResult = innerResult;
}
public AuthenticationHeaderValue Challenge { get; private set; }
public IHttpActionResult InnerResult { get; private set; }
public async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
HttpResponseMessage response = await InnerResult.ExecuteAsync(cancellationToken);
if (response.StatusCode == HttpStatusCode.Unauthorized)
{
// Only add one challenge per authentication scheme.
if (!response.Headers.WwwAuthenticate.Any((h) => h.Scheme == Challenge.Scheme))
{
response.Headers.WwwAuthenticate.Add(Challenge);
}
}
return response;
}
}
This code is from or a derivative of this article Authentication Filters in ASP.NET Web API 2 and this article Authentication Filters in ASP.NET Web API 2