Redirect to HTTPS

You can use your own middleware class, but typically I just do something like this in my Startup configuration:

app.Use(async (context, next) =>
{
    if (context.Request.IsHttps)
    {
        await next();
    }
    else
    {
        var withHttps = Uri.UriSchemeHttps + Uri.SchemeDelimiter + context.Request.Uri.GetComponents(UriComponents.AbsoluteUri & ~UriComponents.Scheme, UriFormat.SafeUnescaped);
        context.Response.Redirect(withHttps);
    }
});

What this does is just grab the entire URL, query string and all, and use GetComponents to get everything except the scheme in the URL. Then the HTTPS scheme gets prepended to the components URL.

This will work with the full .NET Framework, for ASP.NET Core, you can do something like this:

app.Use(async (context, next) =>
{
    if (context.Request.IsHttps)
    {
        await next();
    }
    else
    {
        var withHttps = "https://" + context.Request.Host + context.Request.Path;
        context.Response.Redirect(withHttps);
    }
});

This appends the host and the path to the HTTPS scheme. You may want to add other components such as the query and hash, too.


For .NET Core 2.0 and lower (official docs for 2.0):

Use the [RequireHttps] attribute/filter. You can either do this to your controllers:

[RequireHttps]
public class AccountController {
}

Or else add this in your Startup.cs in the ConfigureServices method:

services.Configure<MvcOptions>(options =>
{
    options.Filters.Add(new RequireHttpsAttribute());
}

Also, I just wanted to add that vcsjones' answer is also correct, but you need to be sure to add this code early on in your config, before any other Middleware/code that causes redirects. In my case, I added it just before I added the Identity Framework middleware.


The full answer is in number 1 but don't stop there setting up HTTPS, go the extra step:

1 - We then use the RequireHttpsAttribute to redirect to HTTPS and set the SSL port in the MVC options. We are also reading the SSL port from launchSettings.json but we only need this in Development mode.

2 - Use AddAntiforgery to require HTTPS on your anti-forgery tokens.

3 - Use the NWebsec.AspNetCore.Middleware NuGet package and UseHsts method to enable Strict Transport Security (HSTS) across the site. Don't forget to add the Preload below and submit your site to the HSTS Preload site. More information here and here.

4 - Use NWebsec.AspNetCore.Middleware NuGet package and the UseHpkp method to enable Public Key Pinning (HPKP) across the site. Note that if you make a mistake with this one you are essentially DoS'ing your site. More information here and here.

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.

After all of the above, your Startup class should look something like this:

public class Startup
{
    private readonly int? sslPort;

    public Startup(IHostingEnvironment hostingEnvironment)
    {
        if (hostingEnvironment.IsDevelopment())
        {
            var launchConfiguration = new ConfigurationBuilder()
                .SetBasePath(hostingEnvironment.ContentRootPath)
                .AddJsonFile(@"Properties\launchSettings.json")
                .Build();
            // During development we won't be using port 443.
            this.sslPort = launchConfiguration.GetValue<int>("iisSettings:iisExpress:sslPort");
        }
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services
            .AddAntiforgery(options =>
            {
                options.RequireSsl = true;
            });
            .AddMvc(options =>
            {
                options.Filters.Add(new RequireHttpsAttribute());
                options.SslPort = sslPort;
            });
    }

    public void Configure(IApplicationBuilder application)
    {
        application
            .UseHsts(options => options.MaxAge(days: 18 * 7).IncludeSubdomains().Preload())
            .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: 18 * 7)
                .IncludeSubdomains())
            .UseCsp(options => options
                .UpgradeInsecureRequests(this.sslPort.HasValue ? this.sslPort.Value : 443))
            .UseMvc();
    }
}