Enforce HTTPS in ASP.NET Core
By David Galvan and Rick Anderson
this article shows how to:
- Require HTTPS for all requests.
- Redirect all HTTP requests to HTTPS.
No API can prevent a client from sending sensitive data on the first request.
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.
HTTP redirection to HTTPS causes ERR_INVALID_REDIRECT on the CORS preflight request
Requests to an endpoint using HTTP that are redirected to HTTPS by UseHttpsRedirection fail with ERR_INVALID_REDIRECT
on the CORS preflight request.
API projects can reject HTTP requests rather than use UseHttpsRedirection
to redirect requests to HTTPS.
Require HTTPS
We recommend that production ASP.NET Core web apps use:
- HTTPS Redirection Middleware (UseHttpsRedirection) to redirect HTTP requests to HTTPS.
- HSTS Middleware (UseHsts) to send HTTP Strict Transport Security Protocol (HSTS) headers to clients.
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
The following code calls UseHttpsRedirection in the Program.cs
file:
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();
The preceding highlighted code:
- Uses the default HttpsRedirectionOptions.RedirectStatusCode (Status307TemporaryRedirect).
- Uses the default HttpsRedirectionOptions.HttpsPort (null) unless overridden by the
ASPNETCORE_HTTPS_PORTS
environment variable or IServerAddressesFeature.
We recommend using temporary redirects rather than permanent redirects. Link caching can cause unstable behavior in development environments. If you prefer to send a permanent redirect status code when the app is in a non-Development environment, see the Configure permanent redirects in production section. We recommend using HSTS to signal to clients that only secure resource requests should be sent to the app (only in production).
Port configuration
A port must be available for the middleware to redirect an insecure request to HTTPS. If no port is available:
- Redirection to HTTPS doesn't occur.
- The middleware logs the warning "Failed to determine the https port for redirect."
Specify the HTTPS port using any of the following approaches:
Set the
https_port
host setting:In host configuration.
By setting the
ASPNETCORE_HTTPS_PORTS
environment variable.By adding a top-level entry in
appsettings.json
:{ "https_port": 443, "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*" }
Indicate a port with the secure scheme using the ASPNETCORE_URLS environment variable. The environment variable configures the server. The middleware indirectly discovers the HTTPS port via IServerAddressesFeature. This approach doesn't work in reverse proxy deployments.
The ASP.NET Core web templates set an HTTPS URL in
Properties/launchsettings.json
for both Kestrel and IIS Express.launchsettings.json
is only used on the local machine.Configure an HTTPS URL endpoint for a public-facing edge deployment of Kestrel server or HTTP.sys server. Only one HTTPS port is used by the app. The middleware discovers the port via IServerAddressesFeature.
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
When Kestrel or HTTP.sys is used as a public-facing edge server, Kestrel or HTTP.sys must be configured to listen on both:
- The secure port where the client is redirected (typically, 443 in production and 5001 in development).
- The insecure port (typically, 80 in production and 5000 in development).
The insecure port must be accessible by the client in order for the app to receive an insecure request and redirect the client to the secure port.
For more information, see Kestrel endpoint configuration or HTTP.sys web server implementation in ASP.NET Core.
Deployment scenarios
Any firewall between the client and server must also have communication ports open for traffic.
If requests are forwarded in a reverse proxy configuration, use Forwarded Headers Middleware before calling HTTPS Redirection Middleware. Forwarded Headers Middleware updates the Request.Scheme
, using the X-Forwarded-Proto
header. The middleware permits redirect URIs and other security policies to work correctly. When Forwarded Headers Middleware isn't used, the backend app might not receive the correct scheme and end up in a redirect loop. A common end user error message is that too many redirects have occurred.
When deploying to Azure App Service, follow the guidance in Tutorial: Bind an existing custom SSL certificate to Azure Web Apps.
Options
The following highlighted code calls AddHttpsRedirection to configure middleware 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();
Calling AddHttpsRedirection
is only necessary to change the values of HttpsPort
or RedirectStatusCode
.
The preceding highlighted code:
- Sets HttpsRedirectionOptions.RedirectStatusCode to Status307TemporaryRedirect, which is the default value. Use the fields of the StatusCodes class for assignments to
RedirectStatusCode
. - Sets the HTTPS port to 5001.
Configure permanent redirects in production
The middleware defaults to sending a Status307TemporaryRedirect with all redirects. If you prefer to send a permanent redirect status code when the app is in a non-Development environment, wrap the middleware options configuration in a conditional check for a non-Development environment.
When configuring services in Program.cs
:
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
An alternative to using HTTPS Redirection Middleware (UseHttpsRedirection
) is to use URL Rewriting Middleware (AddRedirectToHttps
). AddRedirectToHttps
can also set the status code and port when the redirect is executed. For more information, see URL Rewriting Middleware.
When redirecting to HTTPS without the requirement for additional redirect rules, we recommend using HTTPS Redirection Middleware (UseHttpsRedirection
) described in this article.
HTTP Strict Transport Security Protocol (HSTS)
Per OWASP, HTTP Strict Transport Security (HSTS) is an opt-in security enhancement that's specified by a web app through the use of a response header. When a browser that supports HSTS receives this header:
- The browser stores configuration for the domain that prevents sending any communication over HTTP. The browser forces all communication over HTTPS.
- The browser prevents the user from using untrusted or invalid certificates. The browser disables prompts that allow a user to temporarily trust such a certificate.
Because HSTS is enforced by the client, it has some limitations:
- The client must support HSTS.
- HSTS requires at least one successful HTTPS request to establish the HSTS policy.
- The application must check every HTTP request and redirect or reject the HTTP request.
ASP.NET Core implements HSTS with the UseHsts extension method. The following code calls UseHsts
when the app isn't in development mode:
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();
UseHsts
isn't recommended in development because the HSTS settings are highly cacheable by browsers. By default, UseHsts
excludes the local loopback address.
For production environments that are implementing HTTPS for the first time, set the initial HstsOptions.MaxAge to a small value using one of the TimeSpan methods. Set the value from hours to no more than a single day in case you need to revert the HTTPS infrastructure to HTTP. After you're confident in the sustainability of the HTTPS configuration, increase the HSTS max-age
value; a commonly used value is one year.
The following highlighted code:
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();
- Sets the preload parameter of the
Strict-Transport-Security
header. Preload isn't part of the RFC HSTS specification, but is supported by web browsers to preload HSTS sites on fresh install. For more information, see https://hstspreload.org/. - Enables includeSubDomain, which applies the HSTS policy to Host subdomains.
- Explicitly sets the
max-age
parameter of theStrict-Transport-Security
header to 60 days. If not set, defaults to 30 days. For more information, see the max-age directive. - Adds
example.com
to the list of hosts to exclude.
UseHsts
excludes the following loopback hosts:
localhost
: The IPv4 loopback address.127.0.0.1
: The IPv4 loopback address.[::1]
: The IPv6 loopback address.
Opt-out of HTTPS/HSTS on project creation
In some backend service scenarios where connection security is handled at the public-facing edge of the network, configuring connection security at each node isn't required. Web apps that are generated from the templates in Visual Studio or from the dotnet new command enable HTTPS redirection and HSTS. For deployments that don't require these scenarios, you can opt-out of HTTPS/HSTS when the app is created from the template.
To opt-out of HTTPS/HSTS:
Uncheck the Configure for HTTPS checkbox.
Trust the ASP.NET Core HTTPS development certificate on Windows and macOS
For the Firefox browser, see the next section.
The .NET Core SDK includes an HTTPS development certificate. The certificate is installed as part of the first-run experience. For example, dotnet --info
produces a variation of the following output:
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.
Installing the .NET Core SDK installs the ASP.NET Core HTTPS development certificate to the local user certificate store. The certificate has been installed, but it's not trusted. To trust the certificate, perform the one-time step to run the dotnet dev-certs
tool:
dotnet dev-certs https --trust
The following command provides help on the dotnet dev-certs
tool:
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
The Firefox browser uses its own certificate store, and therefore doesn't trust the IIS Express or Kestrel developer certificates.
There are two approaches to trusting the HTTPS certificate with Firefox, create a policy file or configure with the FireFox browser. Configuring with the browser creates the policy file, so the two approaches are equivalent.
Create a policy file to trust HTTPS certificate with Firefox
Create a policy file (policies.json
) at:
- Windows:
%PROGRAMFILES%\Mozilla Firefox\distribution\
- MacOS:
Firefox.app/Contents/Resources/distribution
- Linux: See Trust the certificate with Firefox on Linux in this article.
Add the following JSON to the Firefox policy file:
{
"policies": {
"Certificates": {
"ImportEnterpriseRoots": true
}
}
}
The preceding policy file makes Firefox trust certificates from the trusted certificates in the Windows certificate store. The next section provides an alternative approach to create the preceding policy file by using the Firefox browser.
Configure trust of HTTPS certificate using Firefox browser
Set security.enterprise_roots.enabled
= true
using the following instructions:
- Enter
about:config
in the FireFox browser. - Select Accept the Risk and Continue if you accept the risk.
- Select Show All
- Set
security.enterprise_roots.enabled
=true
- Exit and restart Firefox
For more information, see Setting Up Certificate Authorities (CAs) in Firefox and the mozilla/policy-templates/README file.
How to set up a developer certificate for Docker
See this GitHub issue.
Trust HTTPS certificate on Linux
Establishing trust is distribution and browser specific. The following sections provide instructions for some popular distributions and the Chromium browsers (Edge and Chrome) and for Firefox.
Trust HTTPS certificate on Linux with linux-dev-certs
linux-dev-certs is an open-source, community-supported, .NET global tool that provides a convenient way to create and trust a developer certificate on Linux. The tool is not maintained or supported by Microsoft.
The following commands install the tool and create a trusted developer certificate:
dotnet tool update -g linux-dev-certs
dotnet linux-dev-certs install
For more information or to report issues, see the linux-dev-certs GitHub repository.
Ubuntu trust the certificate for service-to-service communication
The following instructions don't work for some Ubuntu versions, such as 20.04. For more information, see GitHub issue dotnet/AspNetCore.Docs #23686.
Install OpenSSL 1.1.1h or later. See your distribution for instructions on how to update OpenSSL.
Run the following commands:
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
The preceding commands:
- Ensure the current user's developer certificate is created.
- Exports the certificate with elevated permissions needed for the
ca-certificates
folder, using the current user's environment. - Removing the
-E
flag exports the root user certificate, generating it if necessary. Each newly generated certificate has a different thumbprint. When running as root,sudo
and-E
are not needed.
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).
Trust HTTPS certificate on Linux using Edge or Chrome
For chromium browsers on Linux:
Install the
libnss3-tools
for your distribution.Create or verify the
$HOME/.pki/nssdb
folder exists on the machine.Export the certificate with the following command:
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).
Run the following commands:
certutil -d sql:$HOME/.pki/nssdb -A -t "P,," -n localhost -i /usr/local/share/ca-certificates/aspnet/https.crt certutil -d sql:$HOME/.pki/nssdb -A -t "C,," -n localhost -i /usr/local/share/ca-certificates/aspnet/https.crt
Exit and restart the browser.
Trust the certificate with Firefox on Linux
Export the certificate with the following command:
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).
Create a JSON file at
/usr/lib/firefox/distribution/policies.json
with the following command:
cat <<EOF | sudo tee /usr/lib/firefox/distribution/policies.json
{
"policies": {
"Certificates": {
"Install": [
"/usr/local/share/ca-certificates/aspnet/https.crt"
]
}
}
}
EOF
Note: Ubuntu 21.10 Firefox comes as a snap package and the installation folder is /snap/firefox/current/usr/lib/firefox
.
See Configure trust of HTTPS certificate using Firefox browser in this article for an alternative way to configure the policy file using the browser.
Trust the certificate with Fedora 34
See:
- This GitHub comment
- Fedora: Using Shared System Certificates
- Set up a .NET development environment on Fedora.
Trust the certificate with other distros
See this GitHub issue.
Trust HTTPS certificate from Windows Subsystem for Linux
The following instructions don't work for some Linux distributions, such as Ubuntu 20.04. For more information, see GitHub issue dotnet/AspNetCore.Docs #23686.
The Windows Subsystem for Linux (WSL) generates an HTTPS self-signed development certificate, which by default isn't trusted in Windows. The easiest way to have Windows trust the WSL certificate, is to configure WSL to use the same certificate as Windows:
On Windows, export the developer certificate to a file:
dotnet dev-certs https -ep https.pfx -p $CREDENTIAL_PLACEHOLDER$ --trust
Where
$CREDENTIAL_PLACEHOLDER$
is a password.In a WSL window, import the exported certificate on the WSL instance:
dotnet dev-certs https --clean --import <<path-to-pfx>> --password $CREDENTIAL_PLACEHOLDER$
The preceding approach is a one time operation per certificate and per WSL distribution. It's easier than exporting the certificate over and over. If you update or regenerate the certificate on windows, you might need to run the preceding commands again.
Troubleshoot certificate problems such as certificate not trusted
This section provides help when the ASP.NET Core HTTPS development certificate has been installed and trusted, but you still have browser warnings that the certificate is not trusted. The ASP.NET Core HTTPS development certificate is used by Kestrel.
To repair the IIS Express certificate, see this Stackoverflow issue.
All platforms - certificate not trusted
Run the following commands:
dotnet dev-certs https --clean
dotnet dev-certs https --trust
Close any browser instances open. Open a new browser window to app. Certificate trust is cached by browsers.
dotnet dev-certs https --clean Fails
The preceding commands solve most browser trust issues. If the browser is still not trusting the certificate, follow the platform-specific suggestions that follow.
Docker - certificate not trusted
- Delete the C:\Users{USER}\AppData\Roaming\ASP.NET\Https folder.
- Clean the solution. Delete the bin and obj folders.
- Restart the development tool. For example, Visual Studio or Visual Studio Code.
Windows - certificate not trusted
- Check the certificates in the certificate store. There should be a
localhost
certificate with theASP.NET Core HTTPS development certificate
friendly name both underCurrent User > Personal > Certificates
andCurrent User > Trusted root certification authorities > Certificates
- Remove all the found certificates from both Personal and Trusted root certification authorities. Do not remove the IIS Express localhost certificate.
- Run the following commands:
dotnet dev-certs https --clean
dotnet dev-certs https --trust
Close any browser instances open. Open a new browser window to app.
OS X - certificate not trusted
- Open KeyChain Access.
- Select the System keychain.
- Check for the presence of a localhost certificate.
- Check that it contains a
+
symbol on the icon to indicate it's trusted for all users. - Remove the certificate from the system keychain.
- Run the following commands:
dotnet dev-certs https --clean
dotnet dev-certs https --trust
Close any browser instances open. Open a new browser window to app.
See HTTPS Error using IIS Express (dotnet/AspNetCore #16892) for troubleshooting certificate issues with Visual Studio.
Linux certificate not trusted
Check that the certificate being configured for trust is the user HTTPS developer certificate that will be used by the Kestrel server.
Check the current user default HTTPS developer Kestrel certificate at the following location:
ls -la ~/.dotnet/corefx/cryptography/x509stores/my
The HTTPS developer Kestrel certificate file is the SHA1 thumbprint. When the file is deleted via dotnet dev-certs https --clean
, it's regenerated when needed with a different thumbprint.
Check the thumbprint of the exported certificate matches with the following command:
openssl x509 -noout -fingerprint -sha1 -inform pem -in /usr/local/share/ca-certificates/aspnet/https.crt
If the certificate doesn't match, it could be one of the following:
- An old certificate.
- An exported a developer certificate for the root user. For this case, export the certificate.
The root user certificate can be checked at:
ls -la /root/.dotnet/corefx/cryptography/x509stores/my
IIS Express SSL certificate used with Visual Studio
To fix problems with the IIS Express certificate, select Repair from the Visual Studio installer. For more information, see this GitHub issue.
Group policy prevents self-signed certificates from being trusted
In some cases, group policy may prevent self-signed certificates from being trusted. For more information, see this GitHub issue.
Additional information
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 5 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.
Require HTTPS
We recommend that production ASP.NET Core web apps use:
- HTTPS Redirection Middleware (UseHttpsRedirection) to redirect HTTP requests to HTTPS.
- HSTS Middleware (UseHsts) to send HTTP Strict Transport Security Protocol (HSTS) headers to clients.
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
The following code calls UseHttpsRedirection
in the Startup
class:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
The preceding highlighted code:
- Uses the default HttpsRedirectionOptions.RedirectStatusCode (Status307TemporaryRedirect).
- Uses the default HttpsRedirectionOptions.HttpsPort (null) unless overridden by the
ASPNETCORE_HTTPS_PORTS
environment variable or IServerAddressesFeature.
We recommend using temporary redirects rather than permanent redirects. Link caching can cause unstable behavior in development environments. If you prefer to send a permanent redirect status code when the app is in a non-Development environment, see the Configure permanent redirects in production section. We recommend using HSTS to signal to clients that only secure resource requests should be sent to the app (only in production).
Port configuration
A port must be available for the middleware to redirect an insecure request to HTTPS. If no port is available:
- Redirection to HTTPS doesn't occur.
- The middleware logs the warning "Failed to determine the https port for redirect."
Specify the HTTPS port using any of the following approaches:
Set the
https_port
host setting:In host configuration.
By setting the
ASPNETCORE_HTTPS_PORTS
environment variable.By adding a top-level entry in
appsettings.json
:{ "https_port": 443, "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "AllowedHosts": "*" }
Indicate a port with the secure scheme using the ASPNETCORE_URLS environment variable. The environment variable configures the server. The middleware indirectly discovers the HTTPS port via IServerAddressesFeature. This approach doesn't work in reverse proxy deployments.
In development, set an HTTPS URL in
launchsettings.json
. Enable HTTPS when IIS Express is used.Configure an HTTPS URL endpoint for a public-facing edge deployment of Kestrel server or HTTP.sys server. Only one HTTPS port is used by the app. The middleware discovers the port via IServerAddressesFeature.
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
When Kestrel or HTTP.sys is used as a public-facing edge server, Kestrel or HTTP.sys must be configured to listen on both:
- The secure port where the client is redirected (typically, 443 in production and 5001 in development).
- The insecure port (typically, 80 in production and 5000 in development).
The insecure port must be accessible by the client in order for the app to receive an insecure request and redirect the client to the secure port.
For more information, see Kestrel endpoint configuration or HTTP.sys web server implementation in ASP.NET Core.
Deployment scenarios
Any firewall between the client and server must also have communication ports open for traffic.
If requests are forwarded in a reverse proxy configuration, use Forwarded Headers Middleware before calling HTTPS Redirection Middleware. Forwarded Headers Middleware updates the Request.Scheme
, using the X-Forwarded-Proto
header. The middleware permits redirect URIs and other security policies to work correctly. When Forwarded Headers Middleware isn't used, the backend app might not receive the correct scheme and end up in a redirect loop. A common end user error message is that too many redirects have occurred.
When deploying to Azure App Service, follow the guidance in Tutorial: Bind an existing custom SSL certificate to Azure Web Apps.
Options
The following highlighted code calls AddHttpsRedirection to configure middleware options:
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
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");
});
services.AddHttpsRedirection(options =>
{
options.RedirectStatusCode = (int) HttpStatusCode.TemporaryRedirect;
options.HttpsPort = 5001;
});
}
Calling AddHttpsRedirection
is only necessary to change the values of HttpsPort
or RedirectStatusCode
.
The preceding highlighted code:
- Sets HttpsRedirectionOptions.RedirectStatusCode to Status307TemporaryRedirect, which is the default value. Use the fields of the StatusCodes class for assignments to
RedirectStatusCode
. - Sets the HTTPS port to 5001.
Configure permanent redirects in production
The middleware defaults to sending a Status307TemporaryRedirect with all redirects. If you prefer to send a permanent redirect status code when the app is in a non-Development environment, wrap the middleware options configuration in a conditional check for a non-Development environment.
When configuring services in Startup.cs
:
public void ConfigureServices(IServiceCollection services)
{
// IWebHostEnvironment (stored in _env) is injected into the Startup class.
if (!_env.IsDevelopment())
{
services.AddHttpsRedirection(options =>
{
options.RedirectStatusCode = (int) HttpStatusCode.PermanentRedirect;
options.HttpsPort = 443;
});
}
}
HTTPS Redirection Middleware alternative approach
An alternative to using HTTPS Redirection Middleware (UseHttpsRedirection
) is to use URL Rewriting Middleware (AddRedirectToHttps
). AddRedirectToHttps
can also set the status code and port when the redirect is executed. For more information, see URL Rewriting Middleware.
When redirecting to HTTPS without the requirement for additional redirect rules, we recommend using HTTPS Redirection Middleware (UseHttpsRedirection
) described in this article.
HTTP Strict Transport Security Protocol (HSTS)
Per OWASP, HTTP Strict Transport Security (HSTS) is an opt-in security enhancement that's specified by a web app through the use of a response header. When a browser that supports HSTS receives this header:
- The browser stores configuration for the domain that prevents sending any communication over HTTP. The browser forces all communication over HTTPS.
- The browser prevents the user from using untrusted or invalid certificates. The browser disables prompts that allow a user to temporarily trust such a certificate.
Because HSTS is enforced by the client, it has some limitations:
- The client must support HSTS.
- HSTS requires at least one successful HTTPS request to establish the HSTS policy.
- The application must check every HTTP request and redirect or reject the HTTP request.
ASP.NET Core implements HSTS with the UseHsts
extension method. The following code calls UseHsts
when the app isn't in development mode:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
UseHsts
isn't recommended in development because the HSTS settings are highly cacheable by browsers. By default, UseHsts
excludes the local loopback address.
For production environments that are implementing HTTPS for the first time, set the initial HstsOptions.MaxAge to a small value using one of the TimeSpan methods. Set the value from hours to no more than a single day in case you need to revert the HTTPS infrastructure to HTTP. After you're confident in the sustainability of the HTTPS configuration, increase the HSTS max-age
value; a commonly used value is one year.
The following code:
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
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");
});
services.AddHttpsRedirection(options =>
{
options.RedirectStatusCode = (int) HttpStatusCode.TemporaryRedirect;
options.HttpsPort = 5001;
});
}
- Sets the preload parameter of the
Strict-Transport-Security
header. Preload isn't part of the RFC HSTS specification, but is supported by web browsers to preload HSTS sites on fresh install. For more information, see https://hstspreload.org/. - Enables includeSubDomain, which applies the HSTS policy to Host subdomains.
- Explicitly sets the
max-age
parameter of theStrict-Transport-Security
header to 60 days. If not set, defaults to 30 days. For more information, see the max-age directive. - Adds
example.com
to the list of hosts to exclude.
UseHsts
excludes the following loopback hosts:
localhost
: The IPv4 loopback address.127.0.0.1
: The IPv4 loopback address.[::1]
: The IPv6 loopback address.
Opt-out of HTTPS/HSTS on project creation
In some backend service scenarios where connection security is handled at the public-facing edge of the network, configuring connection security at each node isn't required. Web apps that are generated from the templates in Visual Studio or from the dotnet new command enable HTTPS redirection and HSTS. For deployments that don't require these scenarios, you can opt-out of HTTPS/HSTS when the app is created from the template.
To opt-out of HTTPS/HSTS:
Uncheck the Configure for HTTPS checkbox.
Trust the ASP.NET Core HTTPS development certificate on Windows and macOS
For the Firefox browser, see the next section.
The .NET Core SDK includes an HTTPS development certificate. The certificate is installed as part of the first-run experience. For example, running dotnet new webapp
for the first time produces a variation of the following output:
Installed an ASP.NET Core HTTPS development certificate.
To trust the certificate, run 'dotnet dev-certs https --trust'
Learn about HTTPS: https://aka.ms/dotnet-https
Installing the .NET Core SDK installs the ASP.NET Core HTTPS development certificate to the local user certificate store. The certificate has been installed, but it's not trusted. To trust the certificate, perform the one-time step to run the dotnet dev-certs
tool:
dotnet dev-certs https --trust
The following command provides help on the dotnet dev-certs
tool:
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
The Firefox browser uses its own certificate store, and therefore doesn't trust the IIS Express or Kestrel developer certificates.
There are two approaches to trusting the HTTPS certificate with Firefox, create a policy file or configure with the FireFox browser. Configuring with the browser creates the policy file, so the two approaches are equivalent.
Create a policy file to trust HTTPS certificate with Firefox
Create a policy file (policies.json
) at:
- Windows:
%PROGRAMFILES%\Mozilla Firefox\distribution\
- MacOS:
Firefox.app/Contents/Resources/distribution
- Linux: See Trust the certificate with Firefox on Linux later in this article.
Add the following JSON to the Firefox policy file:
{
"policies": {
"Certificates": {
"ImportEnterpriseRoots": true
}
}
}
The preceding policy file makes Firefox trust certificates from the trusted certificates in the Windows certificate store. The next section provides an alternative approach to create the preceding policy file by using the Firefox browser.
Configure trust of HTTPS certificate using Firefox browser
Set security.enterprise_roots.enabled
= true
using the following instructions:
- Enter
about:config
in the FireFox browser. - Select Accept the Risk and Continue if you accept the risk.
- Select Show All.
- Set
security.enterprise_roots.enabled
=true
. - Exit and restart Firefox.
For more information, see Setting Up Certificate Authorities (CAs) in Firefox and the mozilla/policy-templates/README file.
How to set up a developer certificate for Docker
See this GitHub issue.
Trust HTTPS certificate on Linux
Establishing trust is distribution and browser specific. The following sections provide instructions for some popular distributions and the Chromium browsers (Edge and Chrome) and for Firefox.
Ubuntu trust the certificate for service-to-service communication
Install OpenSSL 1.1.1h or later. See your distribution for instructions on how to update OpenSSL.
Run the following commands:
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
The preceding commands:
- Ensure the current user's developer certificate is created.
- Export the certificate with elevated permissions needed for the
ca-certificates
folder, using the current user's environment. - Remove the
-E
flag to export the root user certificate, generating it if necessary. Each newly generated certificate has a different thumbprint. When running as root,sudo
and-E
are not needed.
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).
Trust HTTPS certificate on Linux using Edge or Chrome
For chromium browsers on Linux:
Install the
libnss3-tools
for your distribution.Create or verify the
$HOME/.pki/nssdb
folder exists on the machine.Export the certificate with the following command:
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).
Run the following commands:
certutil -d sql:$HOME/.pki/nssdb -A -t "P,," -n localhost -i /usr/local/share/ca-certificates/aspnet/https.crt certutil -d sql:$HOME/.pki/nssdb -A -t "C,," -n localhost -i /usr/local/share/ca-certificates/aspnet/https.crt
Exit and restart the browser.
Trust the certificate with Firefox on Linux
Export the certificate with the following command:
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).
Create a JSON file at
/usr/lib/firefox/distribution/policies.json
with the following contents:
cat <<EOF | sudo tee /usr/lib/firefox/distribution/policies.json
{
"policies": {
"Certificates": {
"Install": [
"/usr/local/share/ca-certificates/aspnet/https.crt"
]
}
}
}
EOF
See Configure trust of HTTPS certificate using Firefox browser in this article for an alternative way to configure the policy file using the browser.
Trust the certificate with Fedora 34
Firefox on Fedora
echo 'pref("general.config.filename", "firefox.cfg");
pref("general.config.obscure_value", 0);' > ./autoconfig.js
echo '//Enable policies.json
lockPref("browser.policies.perUserDir", false);' > firefox.cfg
echo "{
\"policies\": {
\"Certificates\": {
\"Install\": [
\"aspnetcore-localhost-https.crt\"
]
}
}
}" > policies.json
dotnet dev-certs https -ep localhost.crt --format PEM
sudo mv autoconfig.js /usr/lib64/firefox/
sudo mv firefox.cfg /usr/lib64/firefox/
sudo mv policies.json /usr/lib64/firefox/distribution/
mkdir -p ~/.mozilla/certificates
cp localhost.crt ~/.mozilla/certificates/aspnetcore-localhost-https.crt
rm localhost.crt
Trust dotnet-to-dotnet on Fedora
sudo cp localhost.crt /etc/pki/tls/certs/localhost.pem
sudo update-ca-trust
rm localhost.crt
See this GitHub comment for more information.
Trust the certificate with other distros
See this GitHub issue.
Trust HTTPS certificate from Windows Subsystem for Linux
The Windows Subsystem for Linux (WSL) generates an HTTPS self-signed development certificate. To configure the Windows certificate store to trust the WSL certificate:
Export the developer certificate to a file on Windows:
dotnet dev-certs https -ep C:\<<path-to-folder>>\aspnetcore.pfx -p $CREDENTIAL_PLACEHOLDER$
Where
$CREDENTIAL_PLACEHOLDER$
is a password.In a WSL window, import the exported certificate on the WSL instance:
dotnet dev-certs https --clean --import /mnt/c/<<path-to-folder>>/aspnetcore.pfx -p $CREDENTIAL_PLACEHOLDER$
The preceding approach is a one time operation per certificate and per WSL distribution. It's easier than exporting the certificate over and over. If you update or regenerate the certificate on windows, you might need to run the preceding commands again.
Troubleshoot certificate problems such as certificate not trusted
This section provides help when the ASP.NET Core HTTPS development certificate has been installed and trusted, but you still have browser warnings that the certificate is not trusted. The ASP.NET Core HTTPS development certificate is used by Kestrel.
To repair the IIS Express certificate, see this Stackoverflow issue.
All platforms - certificate not trusted
Run the following commands:
dotnet dev-certs https --clean
dotnet dev-certs https --trust
Close any browser instances that are open. Open a new browser window to the app. Certificate trust is cached by browsers.
dotnet dev-certs https --clean fails
The preceding commands solve most browser trust issues. If the browser is still not trusting the certificate, follow the platform-specific suggestions that follow.
Docker - certificate not trusted
- Delete the C:\Users{USER}\AppData\Roaming\ASP.NET\Https folder.
- Clean the solution. Delete the bin and obj folders.
- Restart the development tool. For example, Visual Studio, Visual Studio Code, or Visual Studio for Mac.
Windows - certificate not trusted
- Check the certificates in the certificate store. There should be a
localhost
certificate with theASP.NET Core HTTPS development certificate
friendly name both underCurrent User > Personal > Certificates
andCurrent User > Trusted root certification authorities > Certificates
- Remove all the found certificates from both Personal and Trusted root certification authorities. Do not remove the IIS Express localhost certificate.
- Run the following commands:
dotnet dev-certs https --clean
dotnet dev-certs https --trust
Close any browser instances that are open. Open a new browser window to the app. Certificate trust is cached by browsers.
OS X - certificate not trusted
- Open KeyChain Access.
- Select the System keychain.
- Check for the presence of a localhost certificate.
- Check that it contains a
+
symbol on the icon to indicate it's trusted for all users. - Remove the certificate from the system keychain.
- Run the following commands:
dotnet dev-certs https --clean
dotnet dev-certs https --trust
Close any browser instances that are open. Open a new browser window to the app. Certificate trust is cached by browsers.
See HTTPS Error using IIS Express (dotnet/AspNetCore #16892) for troubleshooting certificate issues with Visual Studio.
Linux certificate not trusted
Check that the certificate being configured for trust is the user HTTPS developer certificate that will be used by the Kestrel server.
Check the current user default HTTPS developer Kestrel certificate at the following location:
ls -la ~/.dotnet/corefx/cryptography/x509stores/my
The HTTPS developer Kestrel certificate file is the SHA1 thumbprint. When the file is deleted via dotnet dev-certs https --clean
, it's regenerated when needed with a different thumbprint.
Check the thumbprint of the exported certificate matches with the following command:
openssl x509 -noout -fingerprint -sha1 -inform pem -in /usr/local/share/ca-certificates/aspnet/https.crt
If the certificate doesn't match, it could be one of the following:
- An old certificate.
- An exported a developer certificate for the root user. For this case, export the certificate.
The root user certificate can be checked at:
ls -la /root/.dotnet/corefx/cryptography/x509stores/my
IIS Express SSL certificate used with Visual Studio
To fix problems with the IIS Express certificate, select Repair from the Visual Studio installer. For more information, see this GitHub issue.