aspnetcore/security/enforcing-ssl.md
By David Galvan and Rick Anderson
this article shows how to:
No API can prevent a client from sending sensitive data on the first request.
:::moniker range=">= aspnetcore-9.0"
[!WARNING]
API projects
Do not use xref:Microsoft.AspNetCore.Mvc.RequireHttpsAttribute on Web APIs that receive sensitive information.
RequireHttpsAttributeuses 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_URLSenvironment variable or use the--urlscommand line flag. For more information, see xref:fundamentals/environments 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.
<a name="no-http"></a>
Requests to an endpoint using HTTP that are redirected to HTTPS by xref:Microsoft.AspNetCore.Builder.HttpsPolicyBuilderExtensions.UseHttpsRedirection%2A 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.
We recommend that production ASP.NET Core web apps use:
[!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.
The following code calls xref:Microsoft.AspNetCore.Builder.HttpsPolicyBuilderExtensions.UseHttpsRedirection%2A in the Program.cs file:
The preceding highlighted code:
ASPNETCORE_HTTPS_PORT environment variable or xref:Microsoft.AspNetCore.Hosting.Server.Features.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).
A port must be available for the middleware to redirect an insecure request to HTTPS. If no port is available:
Specify the HTTPS port using any of the following approaches:
Set the https_port host setting:
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 xref:Microsoft.AspNetCore.Hosting.Server.Features.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 xref:Microsoft.AspNetCore.Hosting.Server.Features.IServerAddressesFeature.
[!NOTE] When an app is run in a reverse proxy configuration, xref:Microsoft.AspNetCore.Hosting.Server.Features.IServerAddressesFeature isn't available. Set the port using one of the other approaches described in this section.
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 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 xref:fundamentals/servers/httpsys.
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.
The following highlighted code calls xref:Microsoft.AspNetCore.Builder.HttpsRedirectionServicesExtensions.AddHttpsRedirection%2A to configure middleware options:
Calling AddHttpsRedirection is only necessary to change the values of HttpsPort or RedirectStatusCode.
The preceding highlighted code:
RedirectStatusCode.The middleware defaults to sending a xref:Microsoft.AspNetCore.Http.StatusCodes.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:
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.
<a name="hsts"></a>
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:
Because HSTS is enforced by the client, it has some limitations:
ASP.NET Core implements HSTS with the xref:Microsoft.AspNetCore.Builder.HstsBuilderExtensions.UseHsts%2A extension method. The following code calls UseHsts when the app isn't in development mode:
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 xref:Microsoft.AspNetCore.HttpsPolicy.HstsOptions.MaxAge%2A?displayProperty=nameWithType to a small value using one of the xref:System.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:
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/.max-age parameter of the Strict-Transport-Security header to 60 days. If not set, defaults to 30 days. For more information, see the max-age directive.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.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.
Use the --no-https option. For example
dotnet new webapp --no-https
<a name="trust"></a>
The .NET 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 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_CERTIFICATEenvironment variable tofalseprior 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.
See this GitHub issue.
Linux distros differ substantially in how they mark certificates as trusted. While dotnet dev-certs is expected to be broadly applicable it is only officially supported on Ubuntu and Fedora and specifically aims to ensure trust in Firefox and Chromium-based browsers (Edge, Chrome, and Chromium).
To establish OpenSSL trust, the openssl tool must be on the path.
To establish browser trust (for example in Edge or Firefox), the certutil tool must be on the path.
When the ASP.NET Core development certificate is trusted, it is exported to a folder in the current user's home directory. To have OpenSSL (and clients that consume it) pick up this folder, you need to set the SSL_CERT_DIR environment variable. You can either do this in a single session by running a command like export SSL_CERT_DIR=$HOME/.aspnet/dev-certs/trust:/usr/lib/ssl/certs (the exact value will be in the output when --verbose is passed) or by adding it your (distro- and shell-specific) configuration file (for example .profile).
This is required to make tools like curl trust the development certificate. Or, alternatively, you can pass -CAfile or -CApath to each individual curl invocation.
Note that this requires 1.1.1h or later or 3.0.0 or later, depending on which major version you're using.
If OpenSSL trust gets into a bad state (for example if dotnet dev-certs https --clean fails to remove it), it is frequently possible to set things right using the c_rehash tool.
If you're using another browser with its own Network Security Services (NSS) store, you can use the DOTNET_DEV_CERTS_NSSDB_PATHS environment variable to specify a colon-delimited list of NSS directories (for example, the directory containing cert9.db) to which to add the development certificate.
If you store the certificates you want OpenSSL to trust in a specific directory, you can use the DOTNET_DEV_CERTS_OPENSSL_CERTIFICATE_DIRECTORY environment variable to indicate where that is.
[!WARNING] If you set either of these variables, it is important that they are set to the same values each time trust is updated. If they change, the tool won't know about certificates in the former locations (for example to clean them up).
As on other platforms, development certificates are stored and trusted separately for each user. As a result, if you run dotnet dev-certs as a different user (for example by using sudo), it is that user (for example root) that will trust the development certificate.
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.
<a name="tcp"></a>
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.
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.
The preceding commands solve most browser trust issues. If the browser is still not trusting the certificate, follow the platform-specific suggestions that follow.
localhost certificate with the ASP.NET Core HTTPS development certificate friendly name both under Current User > Personal > Certificates and Current User > Trusted root certification authorities > Certificatesdotnet dev-certs https --clean
dotnet dev-certs https --trust
Close any browser instances open. Open a new browser window to app.
+ symbol on the icon to indicate it's trusted for all users.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.
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:
The root user certificate can be checked at:
ls -la /root/.dotnet/corefx/cryptography/x509stores/my
To fix problems with the IIS Express certificate, select Repair from the Visual Studio installer. For more information, see this GitHub issue.
In some cases, group policy may prevent self-signed certificates from being trusted. For more information, see this GitHub issue.
:::moniker-end