ASP.NET Core 2.1.0-preview1: Improvements for using HTTPS

Securing web apps with HTTPS is more important than ever before. Browser enforcement of HTTPS is becoming increasingly strict. Sites that don't use HTTPS are increasingly labeled as insecure. Browsers are also starting to enforce that new and existing web features must only be used from an secure context (Chromium, Mozilla). New privacy requirements like the Global Data Protection Regulation (GDPR) require the use of HTTPS to protect user data. Using HTTPS during development also helps prevent HTTPS related issues before deployment, like insecure links.

ASP.NET Core 2.1 makes it easy to both develop your app with HTTPS enabled and to configure HTTPS once your app is deployed. The ASP.NET Core 2.1 project templates have been updated to enable HTTPS by default. To enable HTTPS in production simply configure the correct server certificate. ASP.NET Core 2.1 also adds support for HTTP Strict Transport Security (HSTS) to enforce HTTPS usage in production and adds improved support for redirecting HTTP traffic to HTTPS endpoints.

HTTPS in development

To get started with ASP.NET Core 2.1 and HTTPS install the .NET Core SDK for 2.1.0-preview1. The SDK will create an HTTPS development certificate for you as part of the first-run experience. For example, when you run dotnet new razor for the first time you should see the following console output:

ASP.NET Core
------------
Successfully installed the ASP.NET Core HTTPS Development Certificate.
To trust the certificate (Windows and macOS only) first install the dev-certs tool by running 'dotnet install tool dotnet-dev-certs -g --version 2.1.0-preview1-final' and then run 'dotnet-dev-certs https --trust'.
For more information on configuring HTTPS see https://go.microsoft.com/fwlink/?linkid=848054.

The ASP.NET Core HTTPS Development Certificate has now been installed into the local user certificate store, but it still needs to be trusted. To trust the certificate you need to perform a one-time step to install and run the new dotnet dev-certs tool as instructed:

C:\WebApplication1>dotnet install tool dotnet-dev-certs -g --version 2.1.0-preview1-final

The installation succeeded. If there are no further instructions, you can type the following command in shell directly to invoke: dotnet-dev-certs

C:\WebApplication1>dotnet dev-certs https --trust
Trusting the HTTPS development certificate was requested. A confirmation prompt will be displayed if the certificate was not previously trusted. Click yes on the prompt to trust the certificate.
A valid HTTPS certificate is already present.

To run the dev-certs tool both dotnet-dev-certs and dotnet dev-certs (without the extra hyphen) will work. Note: If you get an error that the tool was not found you may need to open a new command prompt if the current command prompt was open when the SDK was installed.

On Windows a dialog will pop up to confirm that you want to trust the certificate.

Trust certificate dialog

Click Yes to trust the certificate.

On macOS the certificate will get added to your keychain as a trusted certificate.

On Linux there isn't a standard way across distros to trust the certificate, so you'll need to perform the distro specific guidance for trusting the development certificate.

Run the app by running dotnet run. The ASP.NET Core 2.1 runtime will detect that the development certificate is installed and use the certificate to listen on both http://localhost:5000 and https://localhost:5001:

C:\WebApplication1>dotnet run
Using launch settings from C:\WebApplication1\Properties\launchSettings.json...
Hosting environment: Development
Content root path: C:\WebApplication1
Now listening on: https://localhost:5001
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.

Close any open browsers and then in a new browser window browse to https://localhost:5001 to access the app via HTTPS.

Razor Pages with HTTPS

If you didn't trust the ASP.NET Core development certificate then the browser will display a security warning:

Untrusted certificate warning

You can still click on "Details" to ignore the warning and browse to the site, but you're better off running dotnet dev-certs --trust to trust the certificate. Just run the tool once and you should be all set.

HTTPS redirection

If you browse to the app via http://localhost:5000 you get redirected to the HTTPS endpoint:

HTTPS redirect

This is thanks to the new HTTPS redirection middleware that redirects all HTTP traffic to HTTPS. The middleware will detect available HTTPS server addresses at runtime and redirect accordingly. Otherwise, it redirects to port 443 by default.

The HTTPS redirection middleware is added in app's Configure method:

app.UseHttpsRedirection();

You can configure the HTTPS port explicitly in your ConfigureServices method:

services.AddHttpsRedirection(options => options.HttpsPort = 5002);

Alternatively you can specify the HTTPS port to redirect to using configuration or the ASPNETCORE_HTTPS_PORT environment variable. This is useful for when HTTPS is being handled externally from the app, like when the app is hosted behind IIS. For example, the project template adds the ASPNETCORE_HTTPS_PORT environment variable to the IIS Express launch profile so that it matches the HTTPS port setup for IIS Express:

{
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:51667",
      "sslPort": 44370
    }
  },
  "profiles": {
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development",
        "ASPNETCORE_HTTPS_PORT": "44370"
      }
    }
  }
}

HTTP Strict Transport Security (HSTS)

HSTS is a protocol that instructs browsers to access the site via HTTPS. The protocol has allowances for specifying how long the policy should be enforced (max age) and whether the policy applies to subdomains or not. You can also enable support for your domain to be added to the HSTS preload list.

The ASP.NET Core 2.1 project templates enable support for HSTS by adding the new HSTS middleware in the app's Configure method:

if (env.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}
else
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

Note that HSTS is only enabled when running in a non-development environment. This is to prevent setting an HSTS policy for localhost when in development.

You can configure your HSTS policy (max age, include subdomains, exclude specific domains, support preload) in your ConfigureServices method:

services.AddHsts(options =>
{
    options.MaxAge = TimeSpan.FromDays(100);
    options.IncludeSubDomains = true;
    options.Preload = true;
});

Configuring HTTPS in production

The ASP.NET Core HTTPS development certificate is only for development purposes. In production you need to configure your app for HTTPS including the production certificate that you want to use. Often this is handled externally from the app using a reverse proxy like IIS or NGINX. ASP.NET Core 2.1 adds support to Kestrel for configuring endpoints and HTTPS certificates.

You can still configure server URLs (include HTTPS URLs) using the ASPNETCORE_SERVER_URLS environment variable. To configure the HTTPS certificate for any HTTPS server URLs you configure a default HTTPS certificate.

The default HTTPS certificate can be loaded from a certificate store:

{
  "Kestrel": {
    "Certificates": {
      "Default": {
        "Subject": "mysite",
        "Store": "User",
        "Location": "Local",
        "AllowInvalid": "false" // Set to "true" to allow invalid certificates (e.g. self-signed)
      }
    }
  }
}

Or from a password protected PFX file:

{
  "Kestrel": {
    "Certificates": {
      "Default": {
        "Path": "cert.pfx",
        "Password": "<password>"
      }
    }
  }
}

You can also configure named endpoints for Kestrel that include both the URL for the endpoint and the HTTPS certificate:

{
  "Kestrel": {
    "EndPoints": {
      "Http": {
        "Url": "http://localhost:5005"
      },

      "HttpsInlineCertFile": {
        "Url": "https://localhost:5006",
        "Certificate": {
          "Path": "cert.pfx",
          "Password": "<cert password>"
        }
      },

      "HttpsInlineCertStore": {
        "Url": "https://localhost:5007",
        "Certificate": {
          "Subject": "mysite",
          "Store": "My",
          "Location": "CurrentUser",
          "AllowInvalid": "false" // Set to true to allow invalid certificates (e.g. self-signed)
        }
      }
    }
  }
}

Summary

We hope these new features will make it much easier to use HTTPS during development and in production. Please give the new HTTPS support a try and let us know what you think!