Missing HSTS header on Azure App Service Production slot but appears on Staging slot

Sean Ronan 0 Reputation points
2024-06-22T06:12:32.2233333+00:00

I have deployed the same net core 6.0 mvc website build to an Azure App Service - to both production and staging deployment slots.

My web.config produces the desired HSTS Security header on the staging deployment slot but not the production slot.

  • I have checked that the app service Configuration settings are identical. HTTPS Only = ON
  • I deploy the same build from VSCode using the Azure extension to both Production and Staging
  • There is no code relating to HSTS in my startup.cs or program.cs files
  • The Production slot uses a custom domain name with App Service Managed Certificate, the deployment slot uses the normal *.azurewebsites.net domain with Azure SSL cert.
  • All the other headers specified in the web.config appear on both production and staging slots
  • I am using https://securityheaders.com/ to check the headers on both Production and Staging

What else could cause the HSTS header to be missing on Production?

<configuration>
  <system.webServer>
    <security>
      <requestFiltering removeServerHeader="true" />
    </security>
    <rewrite>
      <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>
      </outboundRules>
    </rewrite>
    <httpProtocol>
      <customHeaders>
        <clear />
        <add name="X-Xss-Protection" value="1; mode=block" />
        <add name="X-Content-Type-Options" value="nosniff" />
        <add name="X-Frame-Options" value="SAMEORIGIN"/>
        <add name="Content-Security-Policy" value="default-src 'self'" />
      </customHeaders>
    </httpProtocol>
  </system.webServer>
</configuration>

Thank you

Azure App Service
Azure App Service
Azure App Service is a service used to create and deploy scalable, mission-critical web apps.
7,914 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Sina Salam 12,011 Reputation points
    2024-06-22T16:12:47.8733333+00:00

    Hello Sean Ronan,

    Welcome to the Microsoft Q&A and thank you for posting your questions here.

    Problem

    I understand that you have deployed a .NET Core 6.0 MVC website to an Azure App Service with both production and staging deployment slots and you are experiencing an issue where the HTTP Strict Transport Security (HSTS) header appears in the staging slot but is missing in the production slot.

    Solution

    Regarding your scenario and information provided, to solve the issue of the missing HSTS header on the production slot of your Azure App Service while it appears on the staging slot, you will need to examine the following steps because the reason could be due to several factors.

    1. Sometimes, the configuration related to custom domains and certificates can affect the headers. Verify that there are no settings or restrictions in the custom domain configuration that could be interfering with the HSTS header. Steps to Check Custom Domain Configuration:
      1. Go to the Azure Portal.
      2. Navigate to your App Service.
      3. Under "Settings," select "Custom domains."
      4. Verify the custom domain settings and ensure there are no rules or configurations that might prevent the HSTS header from being applied. Link: https://learn.microsoft.com/en-us/azure/app-service/app-service-web-tutorial-custom-domain
    2. It's possible that there are differences in the web.config files between the staging and production slots. Although unlikely, but it is advisable to double-check that the web.config file deployed to both slots is indeed identical, especially the sections related to headers and security settings. The below is a revised web.config snippet to ensure proper HSTS header handling:
         <configuration>
           <system.webServer>
             <security>
               <requestFiltering removeServerHeader="true" />
             </security>
             <rewrite>
               <rules>
                 <rule name="Redirect to https" 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>
               </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>
               </outboundRules>
             </rewrite>
             <httpProtocol>
               <customHeaders>
                 <clear />
                 <add name="X-Xss-Protection" value="1; mode=block" />
                 <add name="X-Content-Type-Options" value="nosniff" />
                 <add name="X-Frame-Options" value="SAMEORIGIN"/>
                 <add name="Content-Security-Policy" value="default-src 'self'" />
               </customHeaders>
             </httpProtocol>
           </system.webServer>
         </configuration>
      
      Link1: https://learn.microsoft.com/en-us/azure/app-service/configure-common Link2: https://learn.microsoft.com/en-us/azure/app-service/app-service-web-get-started-dotnet
    3. Even though you mentioned the App Service configurations are identical, reverify specific settings that might impact headers, such as "HTTP Version" or "ARR Affinity."
    4. Determine if there are any intermediate proxies or CDNs (e.g., Azure Front Door, Application Gateway) that might be stripping or modifying the HSTS header. Steps to Check Intermediate Proxies/CDNs:
      1. Identify if any intermediate services are being used.
      2. Review the configuration of these services to ensure they are not configured to strip or modify headers.
      3. Adjust the configuration to allow the HSTS header through if necessary. Link: https://learn.microsoft.com/en-us/azure/application-gateway/overview
    5. Ensure that your web.config is correctly redirecting all HTTP traffic to HTTPS and no HTTP requests are slipping through without being redirected. I provide an example of code snippet is here below:
    <rewrite>
    <rules>
      <rule name="Redirect to https" 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>
    </rules>
    </rewrite>
    

    At this point, use the link provided in the solution to learn more details about recommended solutions, also use the below references for more reading and more areas you review to resolve this kind of the issue.

    References

    1. Verifying web.config Consistency:
    2. Checking Custom Domain Configuration:
    3. Inspecting App Service Configuration:
    4. Checking for Intermediate Proxies or CDNs:
    5. Testing with Direct URLs:
    6. Verifying HTTPS Redirection:
    7. Reviewing Logs and Diagnostics:

    Accept Answer

    I hope this is helpful! Do not hesitate to let me know if you have any other questions.

    ** Please don't forget to close up the thread here by upvoting and accept it as an answer if it is helpful ** so that others in the community facing similar issues can easily find the solution.

    Best Regards,

    Sina Salam


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.