How to Force HTTPS in ASP.NET Core - Windows ASP.NET Core Hosting 2024 | Review and ComparisonWindows ASP.NET Core Hosting 2024 | Review and Comparison

Regardless of the programming framework you use, HTTPS is required to provide security to your web application. But what if a client calls your web application using HTTP rather than HTTPS? How can you make it use HTTPS by force? Let’s explore the options that ASP.NET Core offers.

Use HTTPS Redirection

Redirecting HTTP requests is probably the first thing that comes to mind for you: if a client calls your application using HTTP, your application redirects it to the same URL beginning with HTTPS. Redirecting URLs is a well-known tactic. The web application generates an HTTP response with a Location header and a status code beginning with 3 as in the example below:

HTTP/1.1 301 Moved Permanently
Location: https://www.windowswebhostingreview.com/

Although, as you will discover along the way, this method does not completely address all security risks, it is a good place to start.

Fortunately, you can redirect your client’s requests in ASP.NET Core without going all the way down to the HTTP level. There are several choices available to you. Analyze each of them separately.

The RequireHttps attribute

The RequireHttps attribute is the foundation of the first strategy we’ll examine. As demonstrated in the following code snippet, you may use it in your Razor Pages applications to compel a page to demand HTTPS:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace RazorApp.Pages;

[RequireHttps]
public class PrivacyModel : PageModel
{
  //...existing code...
}

You will automatically receive an HTTPS redirection response if you request this page using HTTP. Only classes that inherit from PageModel are eligible for the RequireHttps attribute when used with Razor Pages. The class methods cannot be added to the attribute’s scope.

You can add the RequireHttps attribute to classes descended from Controller in ASP.NET Core MVC applications, as in the example below:

using System.Diagnostics;
using Microsoft.AspNetCore.Mvc;
using MvcApp.Models;

namespace MvcApp.Controllers;

[RequireHttps]
public class HomeController : Controller
{
  // ...existing code...
}

Any view returned by the controller will have the HTTP redirection applied when the attribute is connected to it. However, you can apply the RequireHttps attribute to particular views in the ASP.NET Core MVC scenario. For instance, the code below demonstrates how to only require HTTPS redirection for the Privacy view.

using System.Diagnostics;
using Microsoft.AspNetCore.Mvc;
using MvcApp.Models;

namespace MvcApp.Controllers;

public class HomeController : Controller
{
    public IActionResult Index()
    {
        return View();
    }

    [RequireHttps]
    public IActionResult Privacy()
    {
        return View();
    }
}

The RequireHttps attribute-based redirection strategy is fairly straightforward. You might also think it’s great to have the option to use HTTPS only for pages with confidential content because you can limit its application to specific pages or views.

Mixing HTTP and HTTPS pages is actually a terrible idea! The vulnerability of your web application to HTTPS downgrade attacks renders it insecure. Make sure that only the HTTPS protocol is used to access all of your web application’s pages in order to reduce this risk.

To lessen the risk, you might consider adding the RequireHttps attribute to every page. However, as you will see in the next section, there are other, better options.

The HTTPS redirection middleware

The method invocation highlighted in the following code snippet is present in the Program.cs file when you create a web application using one of the default ASP.NET project templates:

// Program.cs

var builder = WebApplication.CreateBuilder(args);

// ...existing code...

var app = builder.Build();

// ...existing code...

app.UseHttpsRedirection();  //? HTTPS redirection
app.UseStaticFiles();

app.UseRouting();

// ...existing code...

The HTTPS redirection middleware is activated by calling the UseHttpsRedirection() method. This means that the middleware will examine each request made to your application and may reroute it if necessary. It’s not necessary to search for pages that lack the RequireHttps attribute. Your application’s pages must all use HTTPS. A client will automatically be redirected to the corresponding HTTPS-based URL when it makes an HTTP request for a page.

Enable the HSTS middleware

The UseHttpsRedirection()-based strategy seems great! Your entire web application is made to use the HTTPS protocol with just one line in the Program.cs file.

Unfortunately, despite the fact that this strategy is preferable to mixed-page scenarios, your application could still present some security risks. To stop HTTPS downgrade attacks, forcing clients to switch from HTTP to HTTPS with every request might not be sufficient. Before the client switches to the corresponding HTTPS request, the attacker could intercept the HTTP request.

You need a way to instruct the browser to always use HTTPS when requesting any web application resource. The HTTP Strict-Transport-Security header (HSTS) is one method that is available. The browser will only ever use HTTP to call your application once when using HSTS. Even if a URL is present that uses the HTTP scheme, subsequent requests to the same domain will be made using the HTTPS protocol. Visit this page to learn more about HSTS.

The UseHsts() method in your Program.cs file must be called in order to enable HSTS in your ASP.NET Core application.

// Program.cs

var builder = WebApplication.CreateBuilder(args);

// ...existing code...

var app = builder.Build();

// ...existing code...

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();    //? Enable HSTS middleware
}

// ...existing code...

You can activate the HSTS middleware by calling the UseHsts() method. When you create an application by starting with an ordinary ASP.NET Core template, this code is already present.

Using HSTS in the development environment

You’ll see from the code above that HSTS support is only active if your application is not currently running in your development environment. This selection was made for a useful reason.

Most likely, localhost serves as the domain for your development environment. Any requests made to localhost by your browser will use HTTPS if your development environment employs HSTS. Actually, it’s a good idea to use HTTPS in your development environment. But let’s say you enable HSTS in your ASP.NET Core application. Then, instead of just your ASP.NET Core application or just ASP.NET Core applications in general, it forces your browser to send HTTPS requests to any application hosted on localhost. This could cause problems if, for example, an Angular application that doesn’t use HTTPS suddenly stops functioning.

HSTS settings include an expiration time, which by default is 30 days for ASP.NET Core applications. To change this and other settings, check out the official documentation.

HTTPS Redirection and APIs

We can feel content with the HTTPS security of our ASP.NET Core application at this point, right? Actually not at all. The kind of web application determines this in reality.

Whether you use the RequireHttps attribute or the HTTPS redirection middleware, the HTTPS redirection approach depends on returning to the client a 301 or another 30* HTTP status code. The Strict-Transport-Security header is sent as part of the HSTS method.

Standard browsers are familiar with both strategies. So, application types like ASP.NET Core MVC applications, Razor Pages applications, and Blazor Server applications—whose clients are browsers—can rely on these strategies.

However, non-browser clients, such as API clients, typically disregard those strategies. It’s extremely uncommon for a mobile app or SPA to handle HSTS headers or 301 status codes. You have two options for handling clients that send HTTP requests in this situation:

  • Ignore HTTP requests.
  • Respond with a 400 Bad Request status code.

Ignore HTTP requests

There are several ways to implement the first choice. Using the --urls flag of the dotnet run command, as shown below, is one of the simplest methods.

dotnet run --urls "https://localhost:7123"

This approach allows you to override the URL settings configured in the Properties/launchSettings.json file of your ASP.NET Core project.

The ASPNETCORE_URLS environment variable can be used to override those settings in a way that is more production-focused. The steps to setting this variable in PowerShell are as follows:

$Env: ASPNETCORE_URLS = "https://localhost:7123"

Check out this article to learn other ways to override the current listening URLs in ASP.NET Core.

Treat HTTP requests as bad requests

You must develop your own middleware and use it in place of HSTS middleware and HTTPS redirection if you want to use the Bad Request approach. A straightforward example of such middleware is shown in the following sentence:

// Program.cs

var builder = WebApplication.CreateBuilder(args);

// ...existing code...

var app = builder.Build();

// ...existing code...

// ? new code
//app.UseHttpsRedirection();
app.Use(async (context, next) => {
    if (!context.Request.IsHttps) {
        context.Response.StatusCode = StatusCodes.Status400BadRequest;
        await context.Response.WriteAsync("HTTPS required!");
    } else {
        await next(context);
    }
});
/ ? new code
  
app.UseStaticFiles();

app.UseRouting();

// ...existing code...

The highlighted code demonstrates how the unique middleware replaces the call to the existing UseHttpsRedirection() method. The middleware’s code merely determines whether the current request is HTTPS-secure. If not, it responds with a 400 Bad Request status code and a message informing the user that HTTPS is necessary.

HTTPS Redirection and Reverse Proxies

All of the aforementioned is reasonable if your ASP.NET Core application is directly accessible via the Internet. There is no need to use HTTPS redirection or HSTS middleware if your application is installed in a setting where a reverse proxy manages connection security.

In this situation, you can just delete the method calls for UseHttpsRedirection() and UseHsts() from your ASP.NET Core applications. The same is true for ASP.NET Core Web API applications: to reject HTTP requests, you don’t need to build your own middleware. You give the reverse proxy control and the authority to switch from HTTP to HTTPS.

Summary

This article walked you through the various methods for requiring a client to call an ASP.NET Core application over HTTPS. You began with the straightforward RequireHttps attribute, which pages-by-page redirects to HTTPS-based requests. The UseHttpsRedirection() method, which enables you to apply HTTPS redirection to every page of your application, was then explored.

You discovered that switching from HTTP to HTTPS on every page request does not ensure that you are not at risk of an HTTPS downgrade. By learning about HSTS and the UseHsts() method, you made a further effort to reduce this risk.

You also discovered that, while HTTPS redirection and HSTS are excellent strategies for standard web applications like ASP.NET Core MVC, Razor, and Blazor applications, APIs cannot benefit from them. You must either reject or ignore HTTP requests in this situation.

Finally, only if your deployment environment does not handle protocol switching and control do you need to implement all of these measures. You can assign all these checks to your application, for instance, if it is running behind a reverse proxy.