Search code examples
asp.net-mvcowinazure-web-app-serviceclient-certificatesowin-middleware

Getting client certificates in Azure Web App using OWIN


If you are using Azure Web Apps to host your web application (let it be an ASP.NET MVC web app) you do not have the possibility to set up the IIS behind the Azure Web App to accept client certificates through an HTTPS connection. My application has some Web API endpoints that would be only accessible if the user has the correct certificate with the allowed thumbprint. However, I have other endpoints as well (and of course the website) that would be accessible without a client certificate. So in my case the only way is to accept client certificates.

I am not sure about that, but if I know well I can still get the client certificate by using OWIN while the SSL Settings in IIS is set to Ignore. If I use OWIN and go through the OWIN environment I can see a key called ssl.LoadClientCertAsync.

I am implementing endpoints that a third-party service will call, so I have no control over the content of the request. I know that there is a ssl.ClientCertificate key, with type X509Certificate, but in my case this key doesn't exist.

I have found some C# solution about using this ssl.LoadClientCertAsync key to get the certificate like in the CheckClientCertificate method of Katana or the solution in this C# Corner article. In every solution that I can find in the net, the author gets this type as a Func<Task> and then calls this task, by for example using the await operator.

var certLoader = context.Get<Func<Task>>("ssl.LoadClientCertAsync");
if (certLoader != null)
{
     await certLoader();
...

After that they retrieves the certificate by using the ssl.ClientCertificate key.

    var asyncCert = context.Get<X509Certificate>("ssl.ClientCertificate");

In this example, my asyncCert variable is always null. There weren't any ssl.ClientCertificate key in the OWIN context. I have tried to use the X509Certificate2 instead of X509Certificate, but I still got null.

My question is is it possible to get the client certificate in an Azure Web Site while the default SSL setting is Ignore by using OWIN? If yes, why can't I get the certificate using the ssl.LoadClientCertAsync key?


Solution

  • According to your description, I have created my ASP.NET MVC web application for working with client certificate in OWIN to check this issue. The following code could work on my local side:

    if (Request.GetOwinContext().Environment.Keys.Contains(_owinClientCertKey))
    {
        X509Certificate2 clientCert = Request.GetOwinContext().Get<X509Certificate2>(_owinClientCertKey);
        return Json(new { Thumbprint = clientCert.Thumbprint, Issuer = clientCert.Issuer }, JsonRequestBehavior.AllowGet);
    }
    else
        return Content("There's no client certificate attached to the request.");
    

    For SSL Settings set to Accept, I could select a certificate or cancel the popup window for selecting a certificate.

    enter image description here

    AFAIK, we could enable the client certificate authentication by setting clientCertEnabled to true and this setting is equivalent to SSL Settings Require option in IIS.

    As How To Configure TLS Mutual Authentication for Web App states about accessing the Client Certificate From Your Web App:

    If you are using ASP.NET and configure your app to use client certificate authentication, the certificate will be available through the HttpRequest.ClientCertificate property. For other application stacks, the client cert will be available in your app through a base64 encoded value in the X-ARR-ClientCert request header.

    My question is is it possible to get the client certificate in an Azure Web Site while the default SSL setting is Ignore by using OWIN?

    AFAIK, the current SSL Settings for client certificates only supports Ignore and Require for now. When hosting your web application on azure web app, for the client users who access your azure web app with client certificate authentication, they could specify the certificate to a base64 encoded value as your custom request header when sending request to your azure web app, then your could try to retrieve the header and verify the cert if the cert custom request header exists. Details, you could follow this sample.

    Additionally, you could use Azure VM or Azure Cloud Service instead of azure web app, at this point you could fully control the SSL Settings in IIS.