0

I've setup a reverse proxy in an Azure Web App instance that's rewriting the URL and forcing SSL to our main Azure Web App .NET Application. It's been running well.

We want to deploy client certificate authentication to this .NET Application. We got that working directly to the .NET Application's Azure Web App instance, but we need it to go through the Azure Web App Reverse proxy.

It looks like the reverse proxy is receiving the X-ARR-ClientCert information (I can see it in the fault trace) but isn't passing that information along to the main webserver. I've dug high and low and can't find anything that says this isn't possible. In fact it should be completely possible and there's a bunch of posts saying folks were successful in doing this in IIS.

I'm wondering if I just have a dumb config error in my web.config or if this is a limitation of Azure Web App that isn't documented.

Any help or insight would be amazing. Here's my web.config file where mainazurewebapp.azurewebsites.com is our main .NET App that works if you go there directly and authenticate with your client certificate.

<system.webServer>
    <security>
    <requestFiltering removeServerHeader="true"/>
    </security>
    <httpProtocol>
        <customHeaders>
            <clear />
            <add name="X-Frame-Options" value="SAMEORIGIN" />
            <add name="X-Xss-Protection" value="1; mode=block" />
            <add name="X-Content-Type-Options" value="nosniff" />
        </customHeaders>
    </httpProtocol>
    <httpErrors errorMode="Detailed" />
    <rewrite>
      <rules>
        <rule name="ForceSSL" stopProcessing="true">
                    <match url="(.*)" />
                    <conditions>
                        <add input="{HTTPS}" pattern="^OFF$" ignoreCase="true" />
                    </conditions>
                    <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" />
                </rule>
                
        <rule name="Proxy" stopProcessing="true">
          <match url="(.*)" />
          <action type="Rewrite" url="https://mainazurewebapp.azurewebsites.net/{R:1}"/>
        <serverVariables>
                        <set name="HTTP_X_UNPROXIED_URL" value="https://mainazurewebapp.azurewebsites.net/{R:1}" /> 
                        <set name="HTTP_X_ORIGINAL_ACCEPT_ENCODING" value="{HTTP_ACCEPT_ENCODING}" /> 
                        <set name="HTTP_X_ORIGINAL_HOST" value="{HTTP_HOST}" />
                        <set name="HTTP_ACCEPT_ENCODING" value="" />
            </serverVariables>
        </rule>
      </rules>
     <outboundRules>
                <rule name="Add Strict-Transport-Security only when using HTTPS" enabled="true">
                    <match serverVariable="RESPONSE_Strict_Transport_Security" pattern=".*" />
                    <conditions>
                        <add input="{HTTPS}" pattern="on" ignoreCase="true" />
                    </conditions>
                <action type="Rewrite" value="max-age=31536000; includeSubdomains; preload" />
                </rule>
                                
                <rule name="ChangeReferencesToOriginalUrl" patternSyntax="ExactMatch" preCondition="CheckContentType">
                    <match filterByTags="None" pattern="https://mainazurewebapp.azurewebsites.net" />
                    <action type="Rewrite" value="https://{HTTP_X_ORIGINAL_HOST}" />
                </rule>
                <preConditions>
                    <preCondition name="CheckContentType">
                        <add input="{RESPONSE_CONTENT_TYPE}" pattern="^(text/html|text/plain|text/xml|application/rss\+xml)" />
                    </preCondition>
                </preConditions>
     </outboundRules>
     </rewrite>
  </system.webServer>
</configuration>
mforsetti
  • 2,488
  • 2
  • 14
  • 20

1 Answers1

0

Solved! After a bunch of back and forth emails with Azure Support (who were refreshingly competent), we got the fix.

The main issue was that our reverse proxy Azure web instance is behind Azure's load balancer which means we're technically behind 'another' reverse proxy. So while our reverse proxy was receiving the X-ARR-CLIENTCERT header it was unable to forward it to our main application behind it.

The solution was to rewrite the X-ARR-CLIENTCERT header to a temp header and then update our .net Application to read in from that temp header instead of the default X-ARR-CLIENTCERT.

so we had to update our xdt file to add

<add name="HTTP_X_PRIVATE_TOKEN" xdt:Transform="InsertIfMissing" xdt:Locator="Match(name)" />

and then edit our web.config file to add

<set name="HTTP_X_PRIVATE_TOKEN" value="{HTTP_X_ARR_CLIENTCERT}" />

Then our code just read in HTTP-X-PRIVATE-TOKEN and we were all set.

I spent a bunch of time trying to solve this and thought I'd post the answer here for posterity. I've asked MS to update their documentation to talk a little more about this.