Security and Identity - Enforce HTTPS

In this article

this article shows how to:

No API can prevent a client from sending sensitive data on the first request.

Note If you're using .NET 9 SDK or later, see the updated Linux procedures in the .NET 9 version of this article.

Warning API projects Do not use RequireHttpsAttribute on Web APIs that receive sensitive information. RequireHttpsAttribute uses HTTP status codes to redirect browsers from HTTP to HTTPS. API clients may not understand or obey redirects from HTTP to HTTPS. Such clients may send information over HTTP. Web APIs should either:

Not listen on HTTP. Close the connection with status code 400 (Bad Request) and not serve the request.

To disable HTTP redirection in an API, set the ASPNETCORE_URLS environment variable or use the --urls command line flag. For more information, see Use multiple environments in ASP.NET Core and 8 ways to set the URLs for an ASP.NET Core app by Andrew Lock. HSTS and API projects The default API projects don't include HSTS because HSTS is generally a browser only instruction. Other callers, such as phone or desktop apps, do not obey the instruction. Even within browsers, a single authenticated call to an API over HTTP has risks on insecure networks. The secure approach is to configure API projects to only listen to and respond over HTTPS.

API projects

HSTS and API projects

HTTP redirection to HTTPS causes ERR_INVALID_REDIRECT on the CORS preflight request

Require HTTPS

Note Apps deployed in a reverse proxy configuration allow the proxy to handle connection security (HTTPS). If the proxy also handles HTTPS redirection, there's no need to use HTTPS Redirection Middleware. If the proxy server also handles writing HSTS headers (for example, native HSTS support in IIS 10.0 (1709) or later), HSTS Middleware isn't required by the app. For more information, see Opt-out of HTTPS/HSTS on project creation.

UseHttpsRedirection

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

var app = builder.Build();

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

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

Port configuration

{
  "https_port": 443,
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*"
}

Note When an app is run in a reverse proxy configuration, IServerAddressesFeature isn't available. Set the port using one of the other approaches described in this section.

Edge deployments

Deployment scenarios

Options

using static Microsoft.AspNetCore.Http.StatusCodes;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.AddHsts(options =>
{
    options.Preload = true;
    options.IncludeSubDomains = true;
    options.MaxAge = TimeSpan.FromDays(60);
    options.ExcludedHosts.Add("example.com");
    options.ExcludedHosts.Add("www.example.com");
});

builder.Services.AddHttpsRedirection(options =>
{
    options.RedirectStatusCode = Status307TemporaryRedirect;
    options.HttpsPort = 5001;
});

var app = builder.Build();

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

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

Configure permanent redirects in production

using static Microsoft.AspNetCore.Http.StatusCodes;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

if (!builder.Environment.IsDevelopment())
{
    builder.Services.AddHttpsRedirection(options =>
    {
        options.RedirectStatusCode = Status308PermanentRedirect;
        options.HttpsPort = 443;
    });
}

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");

    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

HTTPS Redirection Middleware alternative approach

HTTP Strict Transport Security Protocol (HSTS)

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

var app = builder.Build();

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

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();
using static Microsoft.AspNetCore.Http.StatusCodes;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.AddHsts(options =>
{
    options.Preload = true;
    options.IncludeSubDomains = true;
    options.MaxAge = TimeSpan.FromDays(60);
    options.ExcludedHosts.Add("example.com");
    options.ExcludedHosts.Add("www.example.com");
});

builder.Services.AddHttpsRedirection(options =>
{
    options.RedirectStatusCode = Status307TemporaryRedirect;
    options.HttpsPort = 5001;
});

var app = builder.Build();

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

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

Opt-out of HTTPS/HSTS on project creation

New ASP.NET Core Web Application dialog showing the Configure for HTTPS checkbox unselected.!

dotnet new webapp --no-https

Trust the ASP.NET Core HTTPS development certificate on Windows and macOS

ASP.NET Core
------------
Successfully installed the ASP.NET Core HTTPS Development Certificate.
To trust the certificate run 'dotnet dev-certs https --trust' (Windows and macOS only).
For establishing trust on other platforms refer to the platform specific documentation.
For more information on configuring HTTPS see https://go.microsoft.com/fwlink/?linkid=848054.
dotnet dev-certs https --trust
dotnet dev-certs https --help

Warning Do not create a development certificate in an environment that will be redistributed, such as a container image or virtual machine. Doing so can lead to spoofing and elevation of privilege. To help prevent this, set the DOTNET_GENERATE_ASPNET_CERTIFICATE environment variable to false prior to calling the .NET CLI for the first time. This will skip the automatic generation of the ASP.NET Core development certificate during the CLI's first-run experience.

Trust the HTTPS certificate with Firefox to prevent SEC_ERROR_INADEQUATE_KEY_USAGE error

Create a policy file to trust HTTPS certificate with Firefox

{
  "policies": {
    "Certificates": {
      "ImportEnterpriseRoots": true
    }
  }
}

Configure trust of HTTPS certificate using Firefox browser

How to set up a developer certificate for Docker

Trust HTTPS certificate on Linux

Trust HTTPS certificate on Linux with linux-dev-certs

dotnet tool update -g linux-dev-certs
dotnet linux-dev-certs install

Ubuntu trust the certificate for service-to-service communication

dotnet dev-certs https
sudo -E dotnet dev-certs https -ep /usr/local/share/ca-certificates/aspnet/https.crt --format PEM
sudo update-ca-certificates

Trust HTTPS certificate on Linux using Edge or Chrome

dotnet dev-certs https
sudo -E dotnet dev-certs https -ep /usr/local/share/ca-certificates/aspnet/https.crt --format PEM

The path in the preceding command is specific for Ubuntu. For other distributions, select an appropriate path or use the path for the Certificate Authorities (CAs).

certutil -d sql:$HOME/.pki/nssdb -A -t "P,," -n localhost -i /usr/local/share/ca-certificates/aspnet/https.crt

Trust the certificate with Firefox on Linux

dotnet dev-certs https
sudo -E dotnet dev-certs https -ep /usr/local/share/ca-certificates/aspnet/https.crt --format PEM

The path in the preceding command is specific for Ubuntu. For other distributions, select an appropriate path or use the path for the Certificate Authorities (CAs).

cat <<EOF | sudo tee /usr/lib/firefox/distribution/policies.json
{
    "policies": {
        "Certificates": {
            "Install": [
                "/usr/local/share/ca-certificates/aspnet/https.crt"
            ]
        }
    }
}
EOF

Warning The following instructions are intended for development purposes only. Do not use the certificates generated in these instructions for a production environment.

Caution Improper use of TLS certificates could lead to spoofing.

Tip Instructions for valid production certificates can be found in the RHEL Documentation. RHEL8 TLS Certificates RHEL9 TLS Certificates RHEL9 Certificate System

Install Dependencies

dnf install nss-tools

Export The ASP.NET Core Development Certificate

Important Replace ${ProjectDirectory} with your projects directory. Replace ${CertificateName} with a name you'll be able to identify in the future.

cd ${ProjectDirectory}
dotnet dev-certs https -ep ${ProjectDirectory}/${CertificateName}.crt --format PEM

Caution If using git, add your certificate to your ${ProjectDirectory}/.gitignore or ${ProjectDirectory}/.git/info/exclude. View the git documentation for information about these files.

Tip You can move your exported certificate outside of your Git repository and replace the occurrences of ${ProjectDirectory}, in the following instructions, with the new location.

Import The ASP.NET Core Development Certificate

Important Replace ${UserProfile} with the profile you intend to use. Do not replace $HOME, it is the environment variable to your user directory.

Chromium-based Browsers

certutil -d sql:$HOME/.pki/nssdb -A -t "P,," -n ${CertificateName} -i ${ProjectDirectory}/${CertificateName}.crt
certutil -d sql:$HOME/.pki/nssdb -A -t "C,," -n ${CertificateName} -i ${ProjectDirectory}/${CertificateName}.crt

Mozilla Firefox

certutil -d sql:$HOME/.mozilla/firefox/${UserProfile}/ -A -t "P,," -n ${CertificateName} -i ${ProjectDirectory}/${CertificateName}.crt
certutil -d sql:$HOME/.mozilla/firefox/${UserProfile}/ -A -t "C,," -n ${CertificateName} -i ${ProjectDirectory}/${CertificateName}.crt

Create An Alias To Test With Curl

Important Don't delete the exported certificate if you plan to test with curl. You'll need to create an alias referencing it in your $SHELL's profile

alias curl="curl --cacert ${ProjectDirectory}/${CertificateName}.crt"

Cleaning up the Development Certificates

certutil -d sql:$HOME/.pki/nssdb -D -n ${CertificateName}
certutil -d sql:$HOME/.mozilla/firefox/${UserProfile}/ -D -n ${CertificateName}
rm ${ProjectDirectory}/${CertificateName}.crt
dotnet dev-certs https --clean

Note Remove the curl alias you created earlier

Trust the certificate with Fedora 34

Trust the certificate with other distros

Trust HTTPS certificate from Windows Subsystem for Linux

Where $CREDENTIAL_PLACEHOLDER$ is a password.

Troubleshoot certificate problems such as certificate not trusted

All platforms - certificate not trusted

dotnet dev-certs https --clean
dotnet dev-certs https --trust

dotnet dev-certs https --clean Fails

Docker - certificate not trusted

Windows - certificate not trusted

dotnet dev-certs https --clean
dotnet dev-certs https --trust

OS X - certificate not trusted

dotnet dev-certs https --clean
dotnet dev-certs https --trust

Linux certificate not trusted

IIS Express SSL certificate used with Visual Studio

Group policy prevents self-signed certificates from being trusted

Additional information

Ref: Enforce HTTPS in ASP.NET Core