Close

Authorizing REST service using an API key

It’s quite common to use an API key as a means to authorize a REST service. The first step is to add a message handler in the Application_Start event of Global.asax:

protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
GlobalConfiguration.Configuration.MessageHandlers.Add(new AuthorizationHeaderHandler());
}

The AuthorizationHandler.cs file is contained in the App_Start folder. On initialization the apiKey and apiKeyEnabled setting are read from the the WebApp AppSettings. If apiKeyEnabled=true and the client doesn’t want to get the metadata (Swagger), then the apiKey is retrieved from the X-Apikey header and compared with the value in the AppSettings. That’s basically it.

using Microsoft.Azure;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks;
using System.Web;

namespace Client.Entities._4PSTrigger.App_Start
{
public class AuthorizationHeaderHandler : DelegatingHandler
{
private static string _apiKey;
private static bool _apiKeyEnabled;

public AuthorizationHeaderHandler()
{
if (string.IsNullOrEmpty(_apiKey))
{
_apiKey = CloudConfigurationManager.GetSetting(“apikey”).ToUpperInvariant();
_apiKeyEnabled = Convert.ToBoolean(CloudConfigurationManager.GetSetting(“apikeyenabled”));
}
}
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
if (!request.RequestUri.AbsoluteUri.ToLowerInvariant().Contains(“swagger”) && _apiKeyEnabled)
{
IEnumerable<string> apiKeyHeaderValues = null;
if (request.Headers.TryGetValues(“X-ApiKey”, out apiKeyHeaderValues))
{
var apiKeyHeaderValue = apiKeyHeaderValues.First();

//Set ClaimSet
var username = (apiKeyHeaderValue == _apiKey ? “ApiManagement” : “OtherUser”);

var usernameClaim = new Claim(ClaimTypes.Name, username);
var identity = new ClaimsIdentity(new[] { usernameClaim }, “ApiKey”);
var principal = new ClaimsPrincipal(identity);

Thread.CurrentPrincipal = principal;
}
else
{
var response = request.CreateErrorResponse(HttpStatusCode.Forbidden, ” { Error : Api-Key is missing} “);

var tsc = new TaskCompletionSource<HttpResponseMessage>();
tsc.SetResult(response); // Also sets the task state to “RanToCompletion”
return tsc.Task;
}
}
return base.SendAsync(request, cancellationToken);
}
}
}