How to force HTTPS using a web.config file

283,749

Solution 1

You need URL Rewrite module, preferably v2 (I have no v1 installed, so cannot guarantee that it will work there, but it should).

Here is an example of such web.config -- it will force HTTPS for ALL resources (using 301 Permanent Redirect):

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <clear />
                <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}{REQUEST_URI}" redirectType="Permanent" appendQueryString="false" />
                </rule>
            </rules>
        </rewrite>
    </system.webServer>
</configuration>

P.S. This particular solution has nothing to do with ASP.NET/PHP or any other technology as it's done using URL rewriting module only -- it is processed at one of the initial/lower levels -- before request gets to the point where your code gets executed.

Solution 2

For those using ASP.NET MVC. You can use the RequireHttpsAttribute to force all responses to be HTTPS:

GlobalFilters.Filters.Add(new RequireHttpsAttribute());

Other things you may also want to do to help secure your site:

  1. Force Anti-Forgery tokens to use SSL/TLS:

    AntiForgeryConfig.RequireSsl = true;
    
  2. Require Cookies to require HTTPS by default by changing the Web.config file:

    <system.web>
        <httpCookies httpOnlyCookies="true" requireSSL="true" />
    </system.web>
    
  3. Use the NWebSec.Owin NuGet package and add the following line of code to enable Strict Transport Security (HSTS) across the site. Don't forget to add the Preload directive below and submit your site to the HSTS Preload site. More information here and here. Note that if you are not using OWIN, there is a Web.config method you can read up on on the NWebSec site.

    // app is your OWIN IAppBuilder app in Startup.cs
    app.UseHsts(options => options.MaxAge(days: 720).Preload());
    
  4. Use the NWebSec.Owin NuGet package and add the following line of code to enable Public Key Pinning (HPKP) across the site. More information here and here.

    // app is your OWIN IAppBuilder app in Startup.cs
    app.UseHpkp(options => options
        .Sha256Pins(
            "Base64 encoded SHA-256 hash of your first certificate e.g. cUPcTAZWKaASuYWhhneDttWpY3oBAkE3h2+soZS7sWs=",
            "Base64 encoded SHA-256 hash of your second backup certificate e.g. M8HztCzM3elUxkcjR2S5P4hhyBNf6lHkmjAHKhpGPWE=")
        .MaxAge(days: 30));
    
  5. Include the https scheme in any URL's used. Content Security Policy (CSP) HTTP header and Subresource Integrity (SRI) do not play nice when you imit the scheme in some browsers. It is better to be explicit about HTTPS. e.g.

    <script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.4/bootstrap.min.js">
    </script>
    
  6. Use the ASP.NET MVC Boilerplate Visual Studio project template to generate a project with all of this and much more built in. You can also view the code on GitHub.

Solution 3

To augment LazyOne's answer, here is an annotated version of the answer.

<rewrite>
  <rules>
     <clear />
     <rule name="Redirect all requests to https" stopProcessing="true">
       <match url="(.*)" />
         <conditions logicalGrouping="MatchAll">
           <add input="{HTTPS}" pattern="off" ignoreCase="true" />
         </conditions>
         <action 
            type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" 
            redirectType="Permanent" appendQueryString="false" />
     </rule>
  </rules>
</rewrite>

Clear all the other rules that might already been defined on this server. Create a new rule, that we will name "Redirect all requests to https". After processing this rule, do not process any more rules! Match all incoming URLs. Then check whether all of these other conditions are true: HTTPS is turned OFF. Well, that's only one condition (but make sure it's true). If it is, send a 301 Permanent redirect back to the client at http://www.foobar.com/whatever?else=the#url-contains. Don't add the query string at the end of that, because it would duplicate the query string!

This is what the properties, attributes, and some of the values mean.

  • clear removes all server rules that we might otherwise inherit.
  • rule defines a rule.
    • name an arbitrary (though unique) name for the rule.
    • stopProcessing whether to forward the request immediately to the IIS request pipeline or first to process additional rules.
  • match when to run this rule.
    • url a pattern against which to evaluate the URL
  • conditions additional conditions about when to run this rule; conditions are processed only if there is first a match.
    • logicalGrouping whether all the conditions must be true (MatchAll) or any of the conditions must be true (MatchAny); similar to AND vs OR.
  • add adds a condition that must be met.
    • input the input that a condition is evaluating; input can be server variables.
    • pattern the standard against which to evaluate the input.
    • ignoreCase whether capitalization matters or not.
  • action what to do if the match and its conditions are all true.
    • type can generally be redirect (client-side) or rewrite (server-side).
    • url what to produce as a result of this rule; in this case, concatenate https:// with two server variables.
    • redirectType what HTTP redirect to use; this one is a 301 Permanent.
    • appendQueryString whether to add the query string at the end of the resultant url or not; in this case, we are setting it to false, because the {REQUEST_URI} already includes it.

The server variables are

  • {HTTPS} which is either OFF or ON.
  • {HTTP_HOST} is www.mysite.com, and
  • {REQUEST_URI} includes the rest of the URI, e.g. /home?key=value
    • the browser handles the #fragment (see comment from LazyOne).

See also: https://www.iis.net/learn/extensions/url-rewrite-module/url-rewrite-module-configuration-reference

Solution 4

The accepted answer did not work for me. I followed the steps on this blog.

A key point that was missing for me was that I needed to download and install the URL Rewrite Tool for IIS. I found it here. The result was the following.

<rewrite>
        <rules>
            <remove name="Http to Https" />
            <rule name="Http to Https" enabled="true" patternSyntax="Wildcard" stopProcessing="true">
                <match url="*" />
                <conditions>
                    <add input="{HTTPS}" pattern="off" />
                </conditions>
                <serverVariables />
                <action type="Redirect" url="https://{HTTPS_HOST}{REQUEST_URI}" />
            </rule>
        </rules>
    </rewrite>

Solution 5

In .Net Core, follow the instructions at https://docs.microsoft.com/en-us/aspnet/core/security/enforcing-ssl

In your startup.cs add the following:

// Requires using Microsoft.AspNetCore.Mvc;
public void ConfigureServices(IServiceCollection services)
{
    services.Configure<MvcOptions>(options =>
    {
        options.Filters.Add(new RequireHttpsAttribute());
    });`enter code here`

To redirect Http to Https, add the following in the startup.cs

// Requires using Microsoft.AspNetCore.Rewrite;
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();

    var options = new RewriteOptions()
       .AddRedirectToHttps();

    app.UseRewriter(options);
Share:
283,749

Related videos on Youtube

Ben Carey
Author by

Ben Carey

For any questions, please feel free to email me at: [email protected]

Updated on July 08, 2022

Comments

  • Ben Carey
    Ben Carey almost 2 years

    I have searched around Google and StackOverflow trying to find a solution to this, but they all seem to relate to ASP.NET etc.

    I usually run Linux on my servers but for this one client I am using Windows with IIS 7.5 (and Plesk 10). This being the reason why I am slightly unfamiliar with IIS and web.config files. In an .htaccess file you can use rewrite conditions to detect whether the protocol is HTTPS and redirect accordingly. Is there a simple way to achieve this using a web.config file, or even using the 'URL Rewrite' module that I have installed?

    I have no experience with ASP.NET so if this is involved in the solution then please include clear steps of how to implement.

    The reason for me doing this with the web.config and not PHP is that I would like to force HTTPS on all assets within the site.

  • LazyOne
    LazyOne over 12 years
    @BenCarey You should also look at Strict-Transport-Security header: en.wikipedia.org/wiki/HTTP_Strict_Transport_Security
  • franzo
    franzo over 10 years
    I recommend changing the redirect so that it doesn't append the query string as it is already part of {REQUEST_URI} (otherwise the parameters get added twice). <action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" redirectType="Permanent" appendQueryString="false" />
  • timbrown
    timbrown over 10 years
    @franzo ^^ this should be the correct answer. definitely doubles up the query string with the other example..
  • Manik Arora
    Manik Arora over 9 years
    I found this link simple and helpful in making any particular page to accept only https requests - support.microsoft.com/kb/239875
  • Muhammad Rehan Saeed
    Muhammad Rehan Saeed over 9 years
    The question asks for ASP.NET but does not state WebForms or MVC, so I gave a comprehensive answer for those using MVC (Which does not use the Web.config file to force HTTPS) and yet...downvoted.
  • Ben Carey
    Ben Carey over 9 years
    I am just speculating, you were probably downvoted because, a) the question was answered 3 years ago, and whilst there may be updates, the solution given still works. And b) because your answer is very complicated for something that is extremely simple. Input is always welcomed on SO, but this answer isn't particularly relevant to the question asked... I may be wrong, it may have been another reason
  • Muhammad Rehan Saeed
    Muhammad Rehan Saeed over 9 years
    a) The solution works but things have changed, this prominent, high rated question deserves an updated answer using what's built into MVC. b) The answer tries to cover all bases. The question is not simple, enabling HTTPS over an entire site requires a lot more than changing a web.config file. Readers may be misled into thinking changing a Web.config file is all it takes. Security is hard enough as it is without incomplete/outdated answers.
  • President James K. Polk
    President James K. Polk over 9 years
    In my opinion this is an excellent and valuable answer. When someone googles the topic and is directed to this question I'm glad your answer is here.
  • redirect
    redirect over 9 years
    Why is the downvote? It works and answers the question.
  • Martyn Chamberlin
    Martyn Chamberlin about 9 years
    Glad that this is ASP.NET agnostic. We've got a pure Angular app that we're running on Windows Azure hosting and this did the track for Angular-specific URLs. I had tried other solutions elsewhere and they broke down for us because they were tied to specific file requests, so on Angular links it didn't work.
  • TheSoftwareJedi
    TheSoftwareJedi about 9 years
    @RehanSaeed Care to elaborate when exactly the original web.config solution would fail?
  • Muhammad Rehan Saeed
    Muhammad Rehan Saeed about 9 years
    @TheSoftwareJedi I never said it would fail. The accepted answer is the equivalent of the RequireHttpsAttribute but it uses IIS rather than MVC to do the redirect. The accepted answer does not address the other pieces of the puzzle you need to apply HTTPS to your site. In particular enabling Strict Transport Security and getting the browser to do the 301 redirect and using the preload mode to add further security.
  • TheSoftwareJedi
    TheSoftwareJedi about 9 years
    @rehansaeed it is not the equivalent of an attribute. The question was about redirecting all http requests to https requests "on all assets within the site." An attribute won't do that, and sts and preload aren't relevant. The question isn't about the proper way to setup and use HTTPS. It is merely a question of redirecting ALL requests.
  • Muhammad Rehan Saeed
    Muhammad Rehan Saeed about 9 years
    @TheSoftwareJedi The correct way to "force HTTPS on all assets within the site" as asked in MVC is to use RequireHttpsAttribute in conjunction with https or scheme-less URL's (See my answer). The questioner only talks about redirecting when talking about PHP and Apache. The questioner has "no experience with ASP.NET", so we need to guide him to the correct path, not the same path used in PHP/Apache.
  • Thomas Bennett
    Thomas Bennett almost 9 years
    This is a down vote because you're telling Google that your file isn't found and then you're using JavaScript to redirect, which is typically just bad.
  • Christiaan Westerbeek
    Christiaan Westerbeek over 8 years
    The regex capturing group has no use, so .* instead of (.*) would work just as fine. Also <action type="Redirect" url="https://{HTTP_HOST}/{R:0}" redirectType="Permanent" /> is shorter.
  • Nathan
    Nathan over 8 years
    @MuhammadRehanSaeed Nice post. Maybe add SRI to your list? scotthelme.co.uk/subresource-integrity
  • Muhammad Rehan Saeed
    Muhammad Rehan Saeed over 8 years
    @Nathan SRI is great but doesn't have anything to so with HTTPS which is what the question is asking. Good mention though.
  • Nathan
    Nathan over 8 years
    @MuhammadRehanSaeed true - I guess your heading of "Other things you may also want to do to help secure your site" made me think of it :)
  • Muhammad Rehan Saeed
    Muhammad Rehan Saeed over 8 years
    @Nathan If you look at the comments of that link, I posted ages ago that I would add that feature to ASP.NET MVC Boilerplate. Still need to do it, would accept a pull-request.
  • AlfaTeK
    AlfaTeK over 8 years
    is it possible to also force to use WWW.domain.com when accessing with a non-www address? so basically 1 redirect to https and WWW URL ?
  • James Wilson
    James Wilson over 8 years
    How do you prevent an SSL error if the SSL cert expires? We just get the FORBIDDEN error from our tests when this happens.
  • LazyOne
    LazyOne over 8 years
    @JamesWilson Unfortunately it has nothing to do with redirects as it cannot be solved using them -- 1) redirect happens after secure connection is already established (where server/browser should prevent from happening with expired cert) and 2) I do not see any variables that would allow to verify expiration date (if such connection is made ignoring expiration). You have to monitor your expiration dates with some specialised tool (or simple ToDo/Reminder kind of app) I'm afraid. Or create yet another test in your test chain which you run first -- check for certificate expiration.
  • LazyOne
    LazyOne over 8 years
    @AlfaTeK You could hardcode domain name in place of {HTTP_HOST} part. Otherwise you would need to use 2 similar rules (extra check for www. presence) -- one for with and one without WWW part.
  • Muhammad Rehan Saeed
    Muhammad Rehan Saeed about 8 years
    @Nathan I've implemented SRI for ASP.NET Core using a TagHelper rehansaeed.com/…
  • Dan Diplo
    Dan Diplo almost 8 years
    I disagree with 5 where you say, "Do not include the scheme of any URL's used in your site or start with https". If a script is served over HTTPS then explicitly request it on HTTPS. It doesn't matter that your site is on HTTP. Most scripts served on both and requested on HTTP just redirect to HTTPS version anyway - so your example of ajax.aspnetcdn.com/ajax/bootstrap/3.3.4/bootstrap.min.js redirects to HTTPS - so save a redirect and serve it from canonical origin.
  • Muhammad Rehan Saeed
    Muhammad Rehan Saeed almost 8 years
    @DanDiplo I've updated 5. Since writing this, I have since learned that the Content-Security-Policy HTTP header and Subresource Integrity do not play nice when you imit the scheme in some browsers. It is better to be explicit about HTTPS.
  • CesarD
    CesarD over 7 years
    What happens for Web Api? There's no RequireHttpsAttribute in Web Api...
  • Muhammad Rehan Saeed
    Muhammad Rehan Saeed over 7 years
  • LazyOne
    LazyOne over 7 years
    One note though: fragment part of URL (from /home?key=value#fragment) is not set to the server by browsers as it meant to be used locally.
  • Shaun Luttin
    Shaun Luttin over 7 years
    @LazyOne Question. We're using the above web.config successfully to redirect from greenearth.game/about#foo to HTTPS. The switch to HTTPS includes the #foo fragment. Given that the #foo part is not sent to the sever, how does the redirect include it?
  • LazyOne
    LazyOne over 7 years
    It's handled by browser. Just open network tab in Google Chrome (or similar in Firefox etc) and see what URL is actually requested (e.g. for http://www.example.com/members#oops request will be sent to http://www.example.com/members which then gets redirected to HTTPS version at https://www.example.com/members -- browser does the rest)
  • Shaun Luttin
    Shaun Luttin over 7 years
    @LazyOne Thank you for that. If I recall correctly, there are a few WebKit bugs that prevent the fragment from being included in redirects. So, this makes sense. bugs.webkit.org/show_bug.cgi?id=24175
  • LazyOne
    LazyOne over 7 years
    en.wikipedia.org/wiki/Fragment_identifier -- "Clients are not supposed to send URI-fragments to servers when they retrieve a document, and without help from a local application (see below) fragments do not participate in HTTP redirections" -- just to be clear in case I misunderstood your last comment.
  • Shaun Luttin
    Shaun Luttin over 7 years
    @lazyone That's useful information. I think you did misunderstand my last comment. What I meant is that, though the client does not send the fragment to the server, the client is involved in preserving the fragment on the client-side during redirects. My comment was linking that to how some WebKit builds fail in that regard. Am I understanding correctly?
  • n0rd
    n0rd about 7 years
    Can it be made optional depending on the app setting in web.config?
  • LazyOne
    LazyOne about 7 years
    @n0rd TBH -- no clue. I'm not a .NET dev so never dealt with app settings stored that way.
  • fotisgpap
    fotisgpap almost 7 years
    just to confirm it works with URL Rewrite module 2.1
  • wezzix
    wezzix almost 7 years
    This works, but unfortunately also on localhost. To avoid this you can add this to <conditions>: <add input="{HTTP_HOST}" pattern="localhost" negate="true" />
  • Kevin R.
    Kevin R. over 6 years
    Using AWS Elastic beanstalk, this method was giving me a 302 Too many redirects until I modified: <match url=".*"/> to <match url="http://*.*" />
  • Nexus
    Nexus over 5 years
    I have a Web API project using Bearer token authentication. This doesn't work, if I try to load my web app (angular-js) over HTTP, it doesn't get redirected. But when I try to sign in (posting to /token), I can see that the XHR was permanently moved. But then it results in a 400 Bad Request, because the request following the preflight is targeting the HTTPS version. Any ideas how I can fix this?
  • Sam
    Sam almost 5 years
    I have applied this procedure to my web.config under the <system.webServer> but I get this when I browse the site "HTTP Error 500.19 - Internal Server Error". Anybody has any ideas?
  • LazyOne
    LazyOne almost 5 years
    @Sam Maybe you do not have URL Rewrite module installed? It does not come with IIS by default, needs to be installed separately. E.g. docs.microsoft.com/en-us/iis/extensions/url-rewrite-module/…
  • Sam
    Sam almost 5 years
    Thanks @LazyOne for the helpful tip. I installed the "URL Rewrite" module and it looks like redirecting. Now I get a "403 - Forbidden: Access is denied." Do you know why is this happening?
  • Sam
    Sam almost 5 years
    BTW, I did turn off "Require SSL" setting on IIS.
  • devio
    devio over 4 years
    I needed this version of URL Rewrite to work on Windows 2016 microsoft.com/en-us/download/details.aspx?id=47337
  • Egli Becerra
    Egli Becerra about 4 years
    in my opinion this is a better answer than the web.config, its simpler and it works wh (en debugging locally without setting exceptions to handle localhost, and for cases when you have modified your host to point to your solution in Visual Studio, works a charm
  • Vishnu Babu
    Vishnu Babu about 3 years
    If you have other rules and this does not work for you try making this the first rule.
  • Shawn
    Shawn over 2 years
    Adding the rewrite tool worked for me. Thanks!