Azure API Management – Securing a Web API hosted as an Azure Web App using client certificates

Azure Api Management acts as a security proxy to 1 or more web services (hosted separately). The intention is that developers will request resources via Azure API Management that will forward the request onto the appropriate web API given appropriate permissions. It is important that the underlying Web Service cannot be accessed directly by an end user (and therefore bypassing the API management security).  To achieve this we are using a client certificate to validate that the request has come from the API management site.

clip_image002

This post describes how to:

  1. Create a self signed certificate
  2. Configure certificates in Azure API Management
  3. Configure the Azure Web App to enable client certificates
  4. Add code to validate a certificate has been provided

 

1) Create a self signed certificate

Run the following example commands to create a self-signed certificate. Tweak the values as required:

makecert.exe -n “CN=Your Issuer Name” -r -sv TempCA.pvk TempCA.cer

makecert.exe -pe -ss My -sr CurrentUser -a sha1 -sky exchange -n “CN=Your subject Name” -eku 1.3.6.1.5.5.7.3.2 -sk SignedByCA -ic TempCA.cer -iv TempCA.pvk

 

2) Configure certificates in Azure API Management

-> Open the Azure API management portal
-> Click APIs –> Choose the appropriate API that you want to secure -> Security -> Manage Certificates
-> Upload the certificate

 

clip_image002

A policy should automatically have been added that intercepts requests and appends the appropriate certificate information before forwarding the request to that Web API. Check the policies section to confirm it has been added. The following screenshot shows the expected policy definition

image

3) Configure the Azure Web App to enable client certificates

Given the Web Api is deployed as an azure App then there is no direct access to IIS to enable client certificate security. Instead configuration must be done either using the Azure REST api; or using the Azure Resource Explorer (preview).

A description of using the REST api is here.

To update is via resource explorer follow these steps:

  • go to https://resources.azure.com/, and log in as you would to the Azure portal
  • find the relevant site, either using the search box or by navigating the tree
  • Switch mode from ‘Read Only’ to ‘Read/Write’
  • click the Edit button
  • Set “clientCertEnabled”: true
  • Click the PUT button at the top

 

4) Add some code to the web api to check the client certificate

This can be done a number of ways. However the following code will perform these checks:

  • · Check time validity of certificate
  • · Check subject name of certificate
  • · Check issuer name of certificate
  • · Check thumbprint of certificate

 

public class BasicCertificateValidator : IValidateCertificates { public bool IsValid(X509Certificate2 certificate) { if (certificate == null) return false; string issuerToMatch = "CN=Your Issuer Name"; string subjectToMatch = "CN=Your subject Name"; string certificateThumbprint = "thumbprintToIndentifyYourCertificate"; // 1. Check time validity of certificate TimeZoneInfo myTimeZone = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time"); var now = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, myTimeZone); DateTime notBefore = certificate.NotBefore; DateTime notAfter = certificate.NotAfter; if (DateTime.Compare(now, notBefore) < 0 && DateTime.Compare(now, notAfter) > 0) return false; // 2. Check subject name of certificate if (!certificate.Subject.Contains(subjectToMatch)) return false; // 3. Check issuer name of certificate if (!certificate.Issuer.Contains(issuerToMatch)) return false; // 4. Check thumprint of certificate if (!certificate.Thumbprint.Trim().Equals(certificateThumbprint, StringComparison.InvariantCultureIgnoreCase)) return false; return true; } public IPrincipal GetPrincipal(X509Certificate2 certificate2) { return new GenericPrincipal(new GenericIdentity(certificate2.Subject), new[] { "User" }); } }

To check on each request to the Web Api add a custom DelegatingHandler. Extend a class from from System.Net.Http.DelegatingHandler and override the SendAsync Message. To access the certificate information you can query the HTTPRequestMessage

public class CertificateAuthHandler : DelegatingHandler { public IValidateCertificates CertificateValidator { get; set; } public CertificateAuthHandler() { CertificateValidator = new BasicCertificateValidator(); } protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { X509Certificate2 certificate = request.GetClientCertificate(); if (certificate == null || !CertificateValidator.IsValid(certificate)) { return Task<HttpResponseMessage>.Factory.StartNew(() => request.CreateResponse(HttpStatusCode.Unauthorized)); } Thread.CurrentPrincipal = CertificateValidator.GetPrincipal(certificate); return base.SendAsync(request, cancellationToken); } }

To add the custom message handler to all new requests add the following code to App_Start/WebApiConfig.cs

GlobalConfiguration.Configuration.MessageHandlers.Add(new CertificateAuthHandler());

 

Happy Coding!

Jon

3 Replies to “Azure API Management – Securing a Web API hosted as an Azure Web App using client certificates”

  1. 414398 245932Wow, incredible weblog structure! How lengthy have you ever been blogging for? you produced running a weblog appear effortless. The full appear of your internet site is amazing, effectively the content material! 781652

  2. 60374 799515I truly appreciated this gorgeous weblog. Make confident you maintain up the very good function. Very best Regards . 177769

Leave a Reply

Your email address will not be published. Required fields are marked *