azureazure-web-app-servicewcf-security

Problem with SSL settings for WCF service running on Azure app service


I'm currently developing a wcf webservice(.NET 4.7.2) that accepts soap messages from different sources. One of the sources requires us to create a endpoint secured by a certificate using a custom authority(CA).

For this, I have created a new .svc file that initializes with the following binding and imports a certificate. This certificate is accessible in the azure web app:

public static void Configure(ServiceConfiguration config)
        {
            // Enable "Add Service Reference" support
            config.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpsGetEnabled = true, HttpGetEnabled = false }); //mex
            //setup support for certficate security
            var binding = new WSHttpBinding
            {
                Name = "CertificateBinding",
                ReaderQuotas = { MaxArrayLength = int.MaxValue },
                MaxReceivedMessageSize = int.MaxValue,
                Security = new WSHttpSecurity
                {
                    Mode = SecurityMode.Transport,
                    Transport = new HttpTransportSecurity
                    {
                        ClientCredentialType = HttpClientCredentialType.Certificate
                    },
                },
            };

            config.EnableProtocol(binding);

            config.Credentials.ServiceCertificate.SetCertificate(StoreLocation.CurrentUser, StoreName.My, X509FindType.FindByThumbprint, "Thumbprint inserted here");

            config.Description.Behaviors.Add(new ServiceDebugBehavior { IncludeExceptionDetailInFaults = true });
        }

To enable certificate authentication for this endpoint I added the following to the web.config;

 <location path="IntegrationWebService_CertificateSecurity.svc">
    <system.webServer>
    <httpErrors errorMode="Detailed"></httpErrors>
      <security>
        <access sslFlags="Ssl, SslNegotiateCert, SslRequireCert" />
      </security>
    </system.webServer>
 </location>

I tested this and this all works well locally, but when deploying to an azure web app it shows a 500 error. I can't seem to figure out the cause of this 500 error. Other .svc files keep working properly.

What I have tried;

Could it be that Azure does not allow a custom value in SslFlags?


Solution

  • Apparently, for Azure, you can't require client certificates using System.ServiceModel. So, first you can turn off the require client certificate part. Doing this using a CustomBinding looks like this:

    var httpsBE = new HttpsTransportBindingElement();
    httpsBE.RequireClientCertificate = false;
    httpsBE.AuthenticationScheme = AuthenticationSchemes.Anonymous;
    

    Go to your App service app settings and require client certificates from there; Azure incoming client certificates appsetting

    Then, what Azure does, is move the certificate from the original request to a X-ARR-ClientCert header. This is accessible in a webservice like this;

    var certHeader = WebOperationContext.Current.IncomingRequest.Headers["X-ARR-ClientCert"];
    

    And to convert it to a X509Certificate2:

    var clientCertBytes = Convert.FromBase64String(certHeader);
    var x509Certificate2 = new X509Certificate2(clientCertBytes);
    

    Then you'd have to run your own certificate validation.