diff --git a/src/WebEid.AspNetCore.Example/Startup.cs b/src/WebEid.AspNetCore.Example/Startup.cs index bbabba4..24f6116 100644 --- a/src/WebEid.AspNetCore.Example/Startup.cs +++ b/src/WebEid.AspNetCore.Example/Startup.cs @@ -38,7 +38,8 @@ namespace WebEid.AspNetCore.Example using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; - + using System.Net; + public class Startup { public Startup(IConfiguration configuration, IWebHostEnvironment environment) @@ -47,6 +48,8 @@ public Startup(IConfiguration configuration, IWebHostEnvironment environment) CurrentEnvironment = environment; } + private static ILogger logger; + private IConfiguration Configuration { get; } private IWebHostEnvironment CurrentEnvironment { get; } @@ -57,7 +60,7 @@ public void ConfigureServices(IServiceCollection services) { builder.AddConsole(); }); - var logger = loggerFactory.CreateLogger("Web-eId ASP.NET Core Example"); + logger = loggerFactory.CreateLogger("Web-eId ASP.NET Core Example"); services.AddSingleton(logger); services.AddRazorPages(options => @@ -83,12 +86,20 @@ public void ConfigureServices(IServiceCollection services) options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute()); }); + var isLoopbackAddressWithHttpProtocol = IsLoopbackAddressWithHttpProtocol(Configuration); services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options => { - options.Cookie.Name = "__Host-WebEid.AspNetCore.Example.Auth"; - options.Cookie.SecurePolicy = CookieSecurePolicy.Always; - options.Cookie.SameSite = SameSiteMode.Strict; + if (isLoopbackAddressWithHttpProtocol) + { + options.Cookie.Name = "WebEid.AspNetCore.Example.Auth"; + } + else + { + options.Cookie.Name = "__Host-WebEid.AspNetCore.Example.Auth"; + options.Cookie.SecurePolicy = CookieSecurePolicy.Always; + } + options.Cookie.SameSite = SameSiteMode.Strict; options.Events.OnRedirectToLogin = context => { context.Response.Redirect("/"); @@ -103,8 +114,15 @@ public void ConfigureServices(IServiceCollection services) services.AddSession(options => { - options.Cookie.Name = "__Host-WebEid.AspNetCore.Example.Session"; - options.Cookie.SecurePolicy = CookieSecurePolicy.Always; + if (isLoopbackAddressWithHttpProtocol) + { + options.Cookie.Name = "WebEid.AspNetCore.Example.Auth"; + } + else + { + options.Cookie.Name = "__Host-WebEid.AspNetCore.Example.Session"; + options.Cookie.SecurePolicy = CookieSecurePolicy.Always; + } options.Cookie.SameSite = SameSiteMode.Strict; options.IdleTimeout = TimeSpan.FromSeconds(60); options.Cookie.IsEssential = true; @@ -124,10 +142,13 @@ public void ConfigureServices(IServiceCollection services) services.AddSingleton(); services.AddSingleton(); - services.AddAntiforgery(options => + if (!isLoopbackAddressWithHttpProtocol) { - options.Cookie.SecurePolicy = CookieSecurePolicy.Always; - }); + services.AddAntiforgery(options => + { + options.Cookie.SecurePolicy = CookieSecurePolicy.Always; + }); + } // Add support for running behind a TLS terminating proxy. services.Configure(options => @@ -147,7 +168,23 @@ private static Uri GetOriginUrl(IConfiguration configuration) throw new ConfigurationErrorsException("OriginUrl is not configured"); } - return new Uri(url); + if (url.EndsWith("/")) + { + throw new ConfigurationErrorsException("Configuration parameter OriginUrl cannot end with '/': " + url); + } + + var uri = new Uri(url); + + if (uri.Scheme.Equals("http") && IsLoopbackAddress(uri.Host)) + { + var uriBuilder = new UriBuilder(uri); + uriBuilder.Scheme = "https"; + var uriHttps = uriBuilder.Uri; + logger.LogWarning("Configuration OriginUrl contains http protocol {}, which is not supported. Replacing it with secure {}", uri, uriHttps); + uri = uriHttps; + } + + return uri; } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. @@ -180,5 +217,30 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) endpoints.MapControllers(); }); } + + private static bool IsLoopbackAddressWithHttpProtocol(IConfiguration configuration) + { + string originUrl = configuration["OriginUrl"]; + return originUrl.StartsWith("http:") && IsLoopbackAddress(new Uri(originUrl).Host); + } + + private static bool IsLoopbackAddress(string host) + { + if (string.IsNullOrEmpty(host)) return false; + + if (host.Equals("localhost", StringComparison.OrdinalIgnoreCase)) + { + return true; + } + + if (IPAddress.TryParse(host, out IPAddress ipAddress)) + { + return IPAddress.IsLoopback(ipAddress); + } + + return false; + } + } + }