Note – You can find the source code of my sample application here(sample does not include HSTS changes)
You can find my all .Net core posts here.
In these series of posts, we will see how to secure your .Net Core applications.
In this post, we will see how to enforce SSL to your .Net Core applications along with adding HSTS to your .Net production site.
From .Net Core 2.1 onwards, HTTPS is enabled by default in every template which is one of the features of .Net Core 2.1
What is SSL?
- SSL (Secure Sockets Layer) is a standard security protocol for establishing encrypted links between a web server and a browser in an online communication
- The usage of SSL technology ensures that all data transmitted between the web server and browser remains encrypted hence secured
To secure your .Net Core applications, you can now enforce the browser to use HTTPS
What is HTTPS?
- Hyper Text Transfer Protocol Secure (HTTPS) is the secure version of HTTP, the protocol over which data is sent between your browser and the website that you are connected to. The ‘S’ at the end of HTTPS stands for ‘Secure’.
- It means all communications between your browser and the website are encrypted.
Let us start.
Prerequisite:
- Visual studio 2017 community edition, download here
- .Net Core 2.0 SDK from here (I have written a post to install SDK here)
Create the MVC Application using .Net Core 2.0 template in VS 2017
Once you have all these installed, open your Visual Studio 2017 -> Create New Project -> Select Core Web application:
Click on Ok and in next window, select Web Application(MVC) as shown below:
Visual Studio will create a well-structured application for you.
Enforcing SSL on Controllers
Enforcing SSL on Controllers is very easy. You just need to add RequireHttps attribute above the controller:
[RequireHttps] public class HomeController: Controller {}
Enforcing SSL globally
As you might have so many controllers and with Controller enforcing you need to make the changes in so many controllers. There is a different approach where you can enforce the SSL globally by making changes in Startup.cs class.
Add below lines in the ConfigureService method:
public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.Configure(options => { options.Filters.Add(new RequireHttpsAttribute()); }); }
Above code requires all requests to useHTTPS
therefore HTTP requests are ignored.
Side Note: Enforcing SSL globally is a good practice and more secure than adding attributes on the controller level. Even if new controllers are added, you would have a headache to add the attributes above all new controllers.
Redirect HTTP to HTTPS
Applications typically need to listen to both HTTP and HTTPS but then it is required to redirect all HTTP traffic to HTTPS.
Add below code in Configure method in Startup.cs class which will redirect all HTTP calls to HTTPS:
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { var options = new RewriteOptions() .AddRedirectToHttps(StatusCodes.Status301MovedPermanently, 63423); app.UseRewriter(options); app.UseMvc(); }
That is it.
Run above application on IIS Express
Please note that if you will run above application on IISExpress then it will throw an error.
This error comes because you have not yet configured your IIS Express settings to allow SSL. You need to Enable SSL.
For that open the properties of the application and then open Debug tab.
Under Web Server setting, check the Enable SSL checkbox as shown below:
Note – You can find the source code of my sample application here.(sample does not include HSTS changes)
HTTP Strict Transport Security (HSTS)
Sometimes just redirecting HTTP to HTTPS is not enough, so there is need of something which can instruct the browsers to always access the site via HTTPS.
What is HSTS?
- HTTP Strict Transport Security (HSTS) is a web security policy mechanism which helps to protect websites against protocol downgrade attacks and cookie hijacking
- It allows web servers to declare that web browsers (or other complying user agents) should only interact with it using secure HTTPS connections, and never via the insecure HTTP protocol
- Typically used only in non-dev scenarios
For example, when you try to access Google with http://www.google.com, the browser will give us 307 status code and will redirect http to https:
For this, we need to tell the application to send below header to the browser when the first time application hits the browser:
Strict-Transport-Security: max-age=31536000
Important Note – The .Net team has announced HSTS middleware with .Net Core 2.1 that supports options for max age, subdomains, and the HSTS preload list. Currently, there are not any straightforward instructions on how to use this with .Net Core 2.1 so we will use NWebSec for HSTS.
Update on 1st March 2018 – .Net Core 2.1 preview 1 is finally out and now the things are clear regarding the use of HSTS with .Net Core. More details here.
Just need to add below lines for HSTS:
app.UseHsts();
We can add some code to the .Net Core application which will do above thing for us.
NWebsec lets you configure quite a few security headers.
Add NWebsec.AspNetCore.Middleware from the Nuget:
Once the Nuget package is installed, add below line of code under Configure method:
app.UseHsts(h=> h.MaxAge(days:365)
Then, You need to submit your domain details on this site HSTS Preload site
and after that add preload as shown below:
app.UseHsts(h=> h.MaxAge(days:365).preload());
Important Note: Note that once you do this, the browser will refuse non-secure requests for your domain, so the only https version of your site will be called. But somehow if your site would not support https in the future then your site would not be accessed once you make above configuration with HSTS. Use it carefully.
Hope it helps.
Great summary – thank you very much!
LikeLiked by 1 person
Thanks a lot Peter.
LikeLike
I believe your code listed under the Redirect HTTP to HTTPS section is missing a part. It should be:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
var options = new RewriteOptions()
.AddRedirectToHttps(StatusCodes.Status301MovedPermanently, 63423);
app.UseRewriter(options);
LikeLike
I believe your code in the Redirect HTTP to HTTPS section is missing a necessary line. It should be the following:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
var options = new RewriteOptions()
.AddRedirectToHttps(StatusCodes.Status301MovedPermanently, 63423);
app.UseRewriter(options);
LikeLiked by 1 person
Oh god, yes you are right Caleb. Important code line with the end bracket was cut somehow. Thanks a lot for pointing this. I really appreciate this.
LikeLike
One thing I don’t understand, though: Why is this the responsibility of the framework? Shouldn’t this be purely implemented in the IIS?
LikeLike
One thing I don’t understand, though: Why is this the responsibility of the framework? Shouldn’t this be purely implemented in the IIS?
LikeLike
Hey, sorry for late reply. Yes I agree with you and I guess we can do that using IIS as well. But still some configurations are required in the framework.
LikeLike
When you have an application that is deployed on multiple platforms you might end up with a multiple of webservers. IIS, Nginx, plain kestrel etc. From a business to customers perspective it is wise to do it in the application middleware so a deployment never ends up with a possible vulnerability. As .NET Core is platform independent you might not know to what platform it might be deployed. So unless there is only one deployment that is managed by yourself, best practice is to do it from the app.
LikeLiked by 1 person
I agree with you, Bert. Thanks for your comment.
LikeLike
Great question,
The foremost reason to do it from the app middleware is to ensure that deployment will not leave room for vulnerabilities.
Let’s say you have an application that you host in the cloud but is also deployed in a customer’s cloud, or maybe even on premises and you’re not the one deploying the app. When the person deploying doesn’t take care of security headers like HSTS the customer might end up with a vulnerable deployment. From my experience the customer will point his finger at you for not supplying a secure app.
So for a small effort in your middleware you end up not being dependent on the deployment for security. Specifically for HSTS you force the person deploying to use a valid certificate because you only allow HTTPS.
Cheers
LikeLiked by 1 person
Wow, very nice explanation Bert. You covered almost everything. Our code should be smart enough to work in any environment. Thanks a lot for your comment.
LikeLike
Yeah that actually makes sense. Thanks.
LikeLiked by 1 person
“That is it.”
For me it’s not.
From IIS Express, it will not redirect from
http://localhost:63009/
to
https://localhost:44320/
Using Chrome or Edge.
LikeLike
I guess it is working for you now, as per your second comment. Correct?
LikeLike
I got it working in Edge. Chrome changes the HTTP to HTTP on port 63009, but when I try HTTP on port 44320, it just hangs.
Also, cannot get any redirection working with IIS with any browser.
LikeLike
What is the issue with the redirection?
LikeLike
I have no idea. Redirection doesn’t work; it just hangs in both browsers when project runs on IIS. I don’t even know where to start.
LikeLike
We are just going to use the Load Balancer to handle this.
LikeLike