Skip to content

Instantly share code, notes, and snippets.

@danroth27
Last active December 6, 2017 19:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danroth27/c942a885ea8f229fe2e62114b8369cde to your computer and use it in GitHub Desktop.
Save danroth27/c942a885ea8f229fe2e62114b8369cde to your computer and use it in GitHub Desktop.
WebDev post: Configuring HTTPS in ASP.NET Core across different platforms
public class EndpointConfiguration
{
public string Host { get; set; }
public int? Port { get; set; }
public string Scheme { get; set; }
public string StoreName { get; set; }
public string StoreLocation { get; set; }
public string FilePath { get; set; }
public string Password { get; set; }
}
[ req ]
default_bits = 2048
default_md = sha256
default_keyfile = key.pem
prompt = no
encrypt_key = no
distinguished_name = req_distinguished_name
req_extensions = v3_req
x509_extensions = v3_req
[ req_distinguished_name ]
commonName = "localhost"
[ v3_req ]
subjectAltName = DNS:localhost
basicConstraints = critical, CA:false
keyUsage = critical, keyEncipherment
extendedKeyUsage = critical, 1.3.6.1.5.5.7.3.1
public static class KestrelServerOptionsExtensions
{
public static void ConfigureEndpoints(this KestrelServerOptions options)
{
var configuration = options.ApplicationServices.GetRequiredService<IConfiguration>();
var environment = options.ApplicationServices.GetRequiredService<IHostingEnvironment>();
var endpoints = configuration.GetSection("HttpServer:Endpoints")
.GetChildren()
.ToDictionary(section => section.Key, section =>
{
var endpoint = new EndpointConfiguration();
section.Bind(endpoint);
return endpoint;
});
foreach (var endpoint in endpoints)
{
var config = endpoint.Value;
var port = config.Port ?? (config.Scheme == "https" ? 443 : 80);
var ipAddresses = new List<IPAddress>();
if (config.Host == "localhost")
{
ipAddresses.Add(IPAddress.IPv6Loopback);
ipAddresses.Add(IPAddress.Loopback);
}
else if (IPAddress.TryParse(config.Host, out var address))
{
ipAddresses.Add(address);
}
else
{
ipAddresses.Add(IPAddress.IPv6Any);
}
foreach (var address in ipAddresses)
{
options.Listen(address, port,
listenOptions =>
{
if (config.Scheme == "https")
{
var certificate = LoadCertificate(config, environment);
listenOptions.UseHttps(certificate);
}
});
}
}
}
private static X509Certificate2 LoadCertificate(EndpointConfiguration config, IHostingEnvironment environment)
{
if (config.StoreName != null && config.StoreLocation != null)
{
using (var store = new X509Store(config.StoreName, Enum.Parse<StoreLocation>(config.StoreLocation)))
{
store.Open(OpenFlags.ReadOnly);
var certificate = store.Certificates.Find(
X509FindType.FindBySubjectName,
config.Host,
validOnly: !environment.IsDevelopment());
if (certificate.Count == 0)
{
throw new InvalidOperationException($"Certificate not found for {config.Host}.");
}
return certificate[0];
}
}
if (config.FilePath != null && config.Password != null)
{
return new X509Certificate2(config.FilePath, config.Password);
}
throw new InvalidOperationException("No valid certificate configuration found for the current endpoint.");
}
}
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:2613/",
"sslPort": 44335
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "https://localhost:44335/",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"KestrelHttpsTest": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "https://localhost:44340",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:8080/"
}
}
}
{
"HttpServer":{
"Endpoints":{
"Http":{
"Host": "localhost",
"Port": 8080,
"Scheme": "http"
},
"Https":{
"Host": "localhost",
"Port": 44340,
"Scheme": "https",
"FilePath": "/path/to/certificate"
}
}
}
}
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseKestrel(options => options.ConfigureEndpoints())
.Build();
}
int? httpsPort = null;
var httpsSection = Configuration.GetSection("HttpServer:Endpoints:Https");
if (httpsSection.Exists())
{
var httpsEndpoint = new EndpointConfiguration();
httpsSection.Bind(httpsEndpoint);
httpsPort = httpsEndpoint.Port;
}
var statusCode = env.IsDevelopment() ? StatusCodes.Status302Found : StatusCodes.Status301MovedPermanently;
app.UseRewriter(new RewriteOptions().AddRedirectToHttps(statusCode, httpsPort));
{
"HttpServer":{
"Endpoints":{
"Http":{
"Host": "localhost",
"Port": 8080,
"Scheme": "http"
},
"Https":{
"Host": "localhost",
"Port": 44340,
"Scheme": "https",
"StoreName": "My",
"StoreLocation": "CurrentUser"
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment