{"id":11865,"date":"2018-02-27T10:01:19","date_gmt":"2018-02-27T18:01:19","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/webdev\/?p=11865"},"modified":"2018-02-27T10:01:19","modified_gmt":"2018-02-27T18:01:19","slug":"asp-net-core-2-1-https-improvements","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/asp-net-core-2-1-https-improvements\/","title":{"rendered":"ASP.NET Core 2.1.0-preview1: Improvements for using HTTPS"},"content":{"rendered":"<p>Securing web apps with HTTPS is more important than ever before. Browser enforcement of HTTPS is becoming increasingly <a href=\"https:\/\/blog.chromium.org\/2017\/04\/next-steps-toward-more-connection.html\">strict<\/a>. Sites that don&#039;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 (<a href=\"https:\/\/www.chromium.org\/Home\/chromium-security\/deprecating-powerful-features-on-insecure-origins\">Chromium<\/a>, <a href=\"https:\/\/blog.mozilla.org\/security\/2018\/01\/15\/secure-contexts-everywhere\/\">Mozilla<\/a>). 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.<\/p>\n<p>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.<\/p>\n<h3 id=\"https-in-development\">HTTPS in development<\/h3>\n<p>To get started with ASP.NET Core 2.1 and HTTPS install the <a href=\"https:\/\/www.microsoft.com\/net\/download\/dotnet-core\/sdk-2.1.300-preview1\">.NET Core SDK for 2.1.0-preview1<\/a>. The SDK will create an HTTPS development certificate for you as part of the first-run experience. For example, when you run <code>dotnet new razor<\/code> for the first time you should see the following console output:<\/p>\n<pre><code>ASP.NET Core\n<span class=\"hljs-comment\">------------<\/span>\nSuccessfully installed <span class=\"hljs-keyword\">the<\/span> ASP.NET Core HTTPS Development Certificate.\nTo trust <span class=\"hljs-keyword\">the<\/span> certificate (Windows <span class=\"hljs-keyword\">and<\/span> macOS only) <span class=\"hljs-keyword\">first<\/span> install <span class=\"hljs-keyword\">the<\/span> dev-certs tool <span class=\"hljs-keyword\">by<\/span> running <span class=\"hljs-string\">'dotnet install tool dotnet-dev-certs -g --version 2.1.0-preview1-final'<\/span> <span class=\"hljs-keyword\">and<\/span> <span class=\"hljs-keyword\">then<\/span> run <span class=\"hljs-string\">'dotnet-dev-certs https --trust'<\/span>.\nFor more information <span class=\"hljs-keyword\">on<\/span> <span class=\"hljs-title\">configuring<\/span> <span class=\"hljs-title\">HTTPS<\/span> <span class=\"hljs-title\">see<\/span> <span class=\"hljs-title\">https<\/span>:\/\/<span class=\"hljs-title\">go<\/span>.<span class=\"hljs-title\">microsoft<\/span>.<span class=\"hljs-title\">com<\/span>\/<span class=\"hljs-title\">fwlink<\/span>\/?<span class=\"hljs-title\">linkid<\/span>=<span class=\"hljs-title\">848054<\/span>.\n<\/code><\/pre>\n<p>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 <code>dotnet dev-certs<\/code> tool as instructed:<\/p>\n<pre><code>C:WebApplication1&gt;dotnet install tool dotnet-dev-certs -g <span class=\"hljs-comment\">--version 2.1.0-preview1-final<\/span>\n\nThe installation succeeded. If there are no further instructions, you can type <span class=\"hljs-keyword\">the<\/span> following <span class=\"hljs-keyword\">command<\/span> <span class=\"hljs-title\">in<\/span> <span class=\"hljs-title\">shell<\/span> <span class=\"hljs-title\">directly<\/span> <span class=\"hljs-title\">to<\/span> <span class=\"hljs-title\">invoke<\/span>: <span class=\"hljs-title\">dotnet-dev-certs<\/span>\n\nC:WebApplication1&gt;dotnet dev-certs <span class=\"hljs-keyword\">https<\/span> <span class=\"hljs-comment\">--trust<\/span>\nTrusting <span class=\"hljs-keyword\">the<\/span> HTTPS development certificate was requested. A confirmation prompt will be displayed <span class=\"hljs-keyword\">if<\/span> <span class=\"hljs-keyword\">the<\/span> certificate was <span class=\"hljs-keyword\">not<\/span> previously trusted. Click yes <span class=\"hljs-keyword\">on<\/span> <span class=\"hljs-title\">the<\/span> <span class=\"hljs-title\">prompt<\/span> <span class=\"hljs-title\">to<\/span> <span class=\"hljs-title\">trust<\/span> <span class=\"hljs-title\">the<\/span> <span class=\"hljs-title\">certificate<\/span>.\nA valid HTTPS certificate is already present.\n<\/code><\/pre>\n<p>To run the <code>dev-certs<\/code> tool both <code>dotnet-dev-certs<\/code> and <code>dotnet dev-certs<\/code> (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.<\/p>\n<p>On Windows a dialog will pop up to confirm that you want to trust the certificate. <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2018\/02\/trust-cert-dialog-2.png\" alt=\"Trust certificate dialog\"><\/p>\n<p>Click Yes to trust the certificate.<\/p>\n<p>On macOS the certificate will get added to your keychain as a trusted certificate.<\/p>\n<p>On Linux there isn&#039;t a standard way across distros to trust the certificate, so you&#039;ll need to perform the distro specific guidance for trusting the development certificate.<\/p>\n<p>Run the app by running <code>dotnet run<\/code>. The ASP.NET Core 2.1 runtime will detect that the development certificate is installed and use the certificate to listen on both <code>http:\/\/localhost:5000<\/code> <em>and<\/em> <code>https:\/\/localhost:5001<\/code>:<\/p>\n<pre><code><span class=\"hljs-string\">C:<\/span>WebApplication1&gt;dotnet run\nUsing launch settings from <span class=\"hljs-string\">C:<\/span>WebApplication1PropertieslaunchSettings.json...\nHosting <span class=\"hljs-string\">environment:<\/span> Development\nContent root <span class=\"hljs-string\">path:<\/span> <span class=\"hljs-string\">C:<\/span>WebApplication1\nNow listening <span class=\"hljs-string\">on:<\/span> <span class=\"hljs-string\">https:<\/span><span class=\"hljs-comment\">\/\/localhost:5001<\/span>\nNow listening <span class=\"hljs-string\">on:<\/span> <span class=\"hljs-string\">http:<\/span><span class=\"hljs-comment\">\/\/localhost:5000<\/span>\nApplication started. Press Ctrl+C to shut down.\n<\/code><\/pre>\n<p>Close any open browsers and then in a new browser window browse to <code>https:\/\/localhost:5001<\/code> to access the app via HTTPS.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2018\/02\/razor-pages-https-2.png\" alt=\"Razor Pages with HTTPS\"><\/p>\n<p>If you didn&#039;t trust the ASP.NET Core development certificate then the browser will display a security warning:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2018\/02\/untrusted-cert-2.png\" alt=\"Untrusted certificate warning\"><\/p>\n<p>You can still click on &quot;Details&quot; to ignore the warning and browse to the site, but you&#039;re better off running <code>dotnet dev-certs --trust<\/code> to trust the certificate. Just run the tool once and you should be all set.<\/p>\n<h3 id=\"https-redirection\">HTTPS redirection<\/h3>\n<p>If you browse to the app via <code>http:\/\/localhost:5000<\/code> you get redirected to the HTTPS endpoint:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2018\/02\/https-redirect-2.png\" alt=\"HTTPS redirect\"><\/p>\n<p>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.<\/p>\n<p>The HTTPS redirection middleware is added in app&#039;s <code>Configure<\/code> method:<\/p>\n<pre><code class=\"lang-c#\">app.UseHttpsRedirection()<span class=\"hljs-comment\">;<\/span>\n<\/code><\/pre>\n<p>You can configure the HTTPS port explicitly in your <code>ConfigureServices<\/code> method:<\/p>\n<pre><code class=\"lang-c#\">services.AddHttpsRedirection(<span class=\"hljs-keyword\">options<\/span> =&gt; <span class=\"hljs-keyword\">options<\/span>.HttpsPort = <span class=\"hljs-number\">5002<\/span>);\n<\/code><\/pre>\n<p>Alternatively you can specify the HTTPS port to redirect to using configuration or the <code>ASPNETCORE_HTTPS_PORT<\/code> 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 <code>ASPNETCORE_HTTPS_PORT<\/code> environment variable to the IIS Express launch profile so that it matches the HTTPS port setup for IIS Express:<\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"iisSettings\"<\/span>: {\n    <span class=\"hljs-attr\">\"windowsAuthentication\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n    <span class=\"hljs-attr\">\"anonymousAuthentication\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n    <span class=\"hljs-attr\">\"iisExpress\"<\/span>: {\n      <span class=\"hljs-attr\">\"applicationUrl\"<\/span>: <span class=\"hljs-string\">\"http:\/\/localhost:51667\"<\/span>,\n      <span class=\"hljs-attr\">\"sslPort\"<\/span>: <span class=\"hljs-number\">44370<\/span>\n    }\n  },\n  <span class=\"hljs-attr\">\"profiles\"<\/span>: {\n    <span class=\"hljs-attr\">\"IIS Express\"<\/span>: {\n      <span class=\"hljs-attr\">\"commandName\"<\/span>: <span class=\"hljs-string\">\"IISExpress\"<\/span>,\n      <span class=\"hljs-attr\">\"launchBrowser\"<\/span>: <span class=\"hljs-literal\">true<\/span>,\n      <span class=\"hljs-attr\">\"environmentVariables\"<\/span>: {\n        <span class=\"hljs-attr\">\"ASPNETCORE_ENVIRONMENT\"<\/span>: <span class=\"hljs-string\">\"Development\"<\/span>,\n        <span class=\"hljs-attr\">\"ASPNETCORE_HTTPS_PORT\"<\/span>: <span class=\"hljs-string\">\"44370\"<\/span>\n      }\n    }\n  }\n}\n<\/code><\/pre>\n<h3 id=\"http-strict-transport-security-hsts-\">HTTP Strict Transport Security (HSTS)<\/h3>\n<p><a href=\"https:\/\/tools.ietf.org\/html\/rfc6797\">HSTS<\/a> 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.<\/p>\n<p>The ASP.NET Core 2.1 project templates enable support for HSTS by adding the new HSTS middleware in the app&#039;s <code>Configure<\/code> method:<\/p>\n<pre><code class=\"lang-c#\"><span class=\"hljs-keyword\">if<\/span> (env.IsDevelopment())\n{\n    <span class=\"hljs-keyword\">app<\/span>.UseDeveloperExceptionPage();\n}\n<span class=\"hljs-keyword\">else<\/span>\n{\n    <span class=\"hljs-keyword\">app<\/span>.UseExceptionHandler(<span class=\"hljs-string\">\"\/Error\"<\/span>);\n    <span class=\"hljs-keyword\">app<\/span>.UseHsts();\n}\n<\/code><\/pre>\n<p>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.<\/p>\n<p>You can configure your HSTS policy (max age, include subdomains, exclude specific domains, support preload) in your <code>ConfigureServices<\/code> method:<\/p>\n<pre><code class=\"lang-c#\">services.AddHsts(<span class=\"hljs-keyword\">options<\/span> =&gt;\n{\n    <span class=\"hljs-keyword\">options<\/span>.MaxAge = TimeSpan.FromDays(<span class=\"hljs-number\">100<\/span>);\n    <span class=\"hljs-keyword\">options<\/span>.IncludeSubDomains = <span class=\"hljs-keyword\">true<\/span>;\n    <span class=\"hljs-keyword\">options<\/span>.Preload = <span class=\"hljs-keyword\">true<\/span>;\n});\n<\/code><\/pre>\n<h3 id=\"configuring-https-in-production\">Configuring HTTPS in production<\/h3>\n<p>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.<\/p>\n<p>You can still configure server URLs (include HTTPS URLs) using the <code>ASPNETCORE_SERVER_URLS<\/code> environment variable. To configure the HTTPS certificate for any HTTPS server URLs you configure a default HTTPS certificate.<\/p>\n<p>The default HTTPS certificate can be loaded from a certificate store:<\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"Kestrel\"<\/span>: {\n    <span class=\"hljs-attr\">\"Certificates\"<\/span>: {\n      <span class=\"hljs-attr\">\"Default\"<\/span>: {\n        <span class=\"hljs-attr\">\"Subject\"<\/span>: <span class=\"hljs-string\">\"mysite\"<\/span>,\n        <span class=\"hljs-attr\">\"Store\"<\/span>: <span class=\"hljs-string\">\"User\"<\/span>,\n        <span class=\"hljs-attr\">\"Location\"<\/span>: <span class=\"hljs-string\">\"Local\"<\/span>,\n        <span class=\"hljs-attr\">\"AllowInvalid\"<\/span>: <span class=\"hljs-string\">\"false\"<\/span> \/\/ Set to <span class=\"hljs-string\">\"true\"<\/span> to allow invalid certificates (e.g. self-signed)\n      }\n    }\n  }\n}\n<\/code><\/pre>\n<p>Or from a password protected PFX file:<\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"Kestrel\"<\/span>: {\n    <span class=\"hljs-attr\">\"Certificates\"<\/span>: {\n      <span class=\"hljs-attr\">\"Default\"<\/span>: {\n        <span class=\"hljs-attr\">\"Path\"<\/span>: <span class=\"hljs-string\">\"cert.pfx\"<\/span>,\n        <span class=\"hljs-attr\">\"Password\"<\/span>: <span class=\"hljs-string\">\"&lt;password&gt;\"<\/span>\n      }\n    }\n  }\n}\n<\/code><\/pre>\n<p>You can also configure named endpoints for Kestrel that include both the URL for the endpoint and the HTTPS certificate:<\/p>\n<pre><code class=\"lang-json\">{\n  <span class=\"hljs-attr\">\"Kestrel\"<\/span>: {\n    <span class=\"hljs-attr\">\"EndPoints\"<\/span>: {\n      <span class=\"hljs-attr\">\"Http\"<\/span>: {\n        <span class=\"hljs-attr\">\"Url\"<\/span>: <span class=\"hljs-string\">\"http:\/\/localhost:5005\"<\/span>\n      },\n\n      <span class=\"hljs-attr\">\"HttpsInlineCertFile\"<\/span>: {\n        <span class=\"hljs-attr\">\"Url\"<\/span>: <span class=\"hljs-string\">\"https:\/\/localhost:5006\"<\/span>,\n        <span class=\"hljs-attr\">\"Certificate\"<\/span>: {\n          <span class=\"hljs-attr\">\"Path\"<\/span>: <span class=\"hljs-string\">\"cert.pfx\"<\/span>,\n          <span class=\"hljs-attr\">\"Password\"<\/span>: <span class=\"hljs-string\">\"&lt;cert password&gt;\"<\/span>\n        }\n      },\n\n      <span class=\"hljs-attr\">\"HttpsInlineCertStore\"<\/span>: {\n        <span class=\"hljs-attr\">\"Url\"<\/span>: <span class=\"hljs-string\">\"https:\/\/localhost:5007\"<\/span>,\n        <span class=\"hljs-attr\">\"Certificate\"<\/span>: {\n          <span class=\"hljs-attr\">\"Subject\"<\/span>: <span class=\"hljs-string\">\"mysite\"<\/span>,\n          <span class=\"hljs-attr\">\"Store\"<\/span>: <span class=\"hljs-string\">\"My\"<\/span>,\n          <span class=\"hljs-attr\">\"Location\"<\/span>: <span class=\"hljs-string\">\"CurrentUser\"<\/span>,\n          <span class=\"hljs-attr\">\"AllowInvalid\"<\/span>: <span class=\"hljs-string\">\"false\"<\/span> \/\/ Set to <span class=\"hljs-literal\">true<\/span> to allow invalid certificates (e.g. self-signed)\n        }\n      }\n    }\n  }\n}\n<\/code><\/pre>\n<h3 id=\"summary\">Summary<\/h3>\n<p>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!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Securing web apps with HTTPS is more important than ever before. Browser enforcement of HTTPS is becoming increasingly strict. Sites that don&#039;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 [&hellip;]<\/p>\n","protected":false},"author":417,"featured_media":58792,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[197,7509],"tags":[],"class_list":["post-11865","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-aspnet","category-aspnetcore"],"acf":[],"blog_post_summary":"<p>Securing web apps with HTTPS is more important than ever before. Browser enforcement of HTTPS is becoming increasingly strict. Sites that don&#039;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 [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/11865","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/417"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=11865"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/11865\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/58792"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=11865"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=11865"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=11865"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}