How to force HTTPS using a web.config file
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:
-
Force Anti-Forgery tokens to use SSL/TLS:
AntiForgeryConfig.RequireSsl = true;
-
Require Cookies to require HTTPS by default by changing the Web.config file:
<system.web> <httpCookies httpOnlyCookies="true" requireSSL="true" /> </system.web>
-
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());
-
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));
-
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>
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.
-
logicalGrouping whether all the conditions must be true (
-
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 itsconditions
are all true.-
type can generally be
redirect
(client-side) orrewrite
(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.
-
type can generally be
The server variables are
-
{HTTPS}
which is eitherOFF
orON
. -
{HTTP_HOST}
iswww.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).
- the browser handles the
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);
Related videos on Youtube
![Ben Carey](https://i.stack.imgur.com/eJKBB.png?s=256&g=1)
Ben Carey
For any questions, please feel free to email me at: [email protected]
Updated on July 08, 2022Comments
-
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.
-
Chris Moschini almost 9 yearsAnd the inverse: stackoverflow.com/questions/25767014/…
-
RBT almost 6 yearsRelated post - Best way in asp.net to force https for an entire site?
-
-
LazyOne over 12 years@BenCarey You should also look at
Strict-Transport-Security
header: en.wikipedia.org/wiki/HTTP_Strict_Transport_Security -
franzo over 10 yearsI 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 over 10 years@franzo ^^ this should be the correct answer. definitely doubles up the query string with the other example..
-
Manik Arora over 9 yearsI found this link simple and helpful in making any particular page to accept only https requests - support.microsoft.com/kb/239875
-
Muhammad Rehan Saeed over 9 yearsThe 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 over 9 yearsI 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 over 9 yearsa) 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 over 9 yearsIn 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 over 9 yearsWhy is the downvote? It works and answers the question.
-
Martyn Chamberlin about 9 yearsGlad 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 about 9 years@RehanSaeed Care to elaborate when exactly the original web.config solution would fail?
-
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 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 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 almost 9 yearsThis 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 over 8 yearsThe 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 over 8 years@MuhammadRehanSaeed Nice post. Maybe add SRI to your list? scotthelme.co.uk/subresource-integrity
-
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 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 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 over 8 yearsis 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 over 8 yearsHow do you prevent an SSL error if the SSL cert expires? We just get the FORBIDDEN error from our tests when this happens.
-
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 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 forwww.
presence) -- one for with and one without WWW part. -
Muhammad Rehan Saeed about 8 years@Nathan I've implemented SRI for ASP.NET Core using a TagHelper rehansaeed.com/…
-
Dan Diplo almost 8 yearsI 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 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 over 7 yearsWhat happens for Web Api? There's no RequireHttpsAttribute in Web Api...
-
Muhammad Rehan Saeed over 7 years@CesarD See stackoverflow.com/questions/26504409/…
-
LazyOne over 7 yearsOne 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 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 over 7 yearsIt'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 tohttp://www.example.com/members
which then gets redirected to HTTPS version athttps://www.example.com/members
-- browser does the rest) -
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 over 7 yearsen.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 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 about 7 yearsCan it be made optional depending on the app setting in web.config?
-
LazyOne about 7 years@n0rd TBH -- no clue. I'm not a .NET dev so never dealt with app settings stored that way.
-
fotisgpap almost 7 yearsjust to confirm it works with URL Rewrite module 2.1
-
wezzix almost 7 yearsThis 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. over 6 yearsUsing AWS Elastic beanstalk, this method was giving me a 302 Too many redirects until I modified:
<match url=".*"/>
to<match url="http://*.*" />
-
Nexus over 5 yearsI 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 almost 5 yearsI 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 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 almost 5 yearsThanks @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 almost 5 yearsBTW, I did turn off "Require SSL" setting on IIS.
-
devio over 4 yearsI needed this version of URL Rewrite to work on Windows 2016 microsoft.com/en-us/download/details.aspx?id=47337
-
Egli Becerra about 4 yearsin 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 about 3 yearsIf you have other rules and this does not work for you try making this the first rule.
-
Shawn over 2 yearsAdding the rewrite tool worked for me. Thanks!