diff --git a/Dfe.PrepareTransfers.Web/Security/SecureHeadersDefinitions.cs b/Dfe.PrepareTransfers.Web/Security/SecureHeadersDefinitions.cs index f22b1afb1..08bffe7b1 100644 --- a/Dfe.PrepareTransfers.Web/Security/SecureHeadersDefinitions.cs +++ b/Dfe.PrepareTransfers.Web/Security/SecureHeadersDefinitions.cs @@ -9,7 +9,7 @@ public static HeaderPolicyCollection GetHeaderPolicyCollection(bool isDev, Allow { HeaderPolicyCollection policy = new HeaderPolicyCollection() .AddFrameOptionsDeny() - .AddXssProtectionBlock() + .AddXssProtectionDisabled() .AddContentTypeOptionsNoSniff() .AddReferrerPolicyStrictOriginWhenCrossOrigin() .RemoveServerHeader() @@ -35,7 +35,6 @@ public static HeaderPolicyCollection GetHeaderPolicyCollection(bool isDev, Allow .WithNonce(); builder.AddFrameAncestors().None(); }) - .RemoveServerHeader() .AddPermissionsPolicy(builder => { builder.AddAccelerometer().None(); @@ -54,12 +53,6 @@ public static HeaderPolicyCollection GetHeaderPolicyCollection(bool isDev, Allow builder.AddUsb().None(); }); - if (isDev is false) - // max age = one year in seconds - { - policy.AddStrictTransportSecurityMaxAgeIncludeSubDomains(maxAgeInSeconds: 60 * 60 * 24 * 365); - } - return policy; } } diff --git a/Dfe.PrepareTransfers.Web/Startup.cs b/Dfe.PrepareTransfers.Web/Startup.cs index 696a1d1cd..caf4a5b85 100644 --- a/Dfe.PrepareTransfers.Web/Startup.cs +++ b/Dfe.PrepareTransfers.Web/Startup.cs @@ -144,6 +144,15 @@ public void ConfigureServices(IServiceCollection services) // Initialize the ConversionsUrl var serviceLinkOptions = Configuration.GetSection("ServiceLink").Get(); Links.InitializeConversionsUrl(serviceLinkOptions.ConversionsUrl); + + // Enforce HTTPS in ASP.NET Core + // @link https://learn.microsoft.com/en-us/aspnet/core/security/enforcing-ssl? + services.AddHsts(options => + { + options.Preload = true; + options.IncludeSubDomains = true; + options.MaxAge = TimeSpan.FromDays(365); + }); } /// @@ -167,6 +176,15 @@ private AuthorizationPolicyBuilder SetupAuthorizationPolicyBuilder() // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { + // Ensure we do not lose X-Forwarded-* Headers when behind a Proxy + var forwardOptions = new ForwardedHeadersOptions { + ForwardedHeaders = ForwardedHeaders.All, + RequireHeaderSymmetry = false + }; + forwardOptions.KnownNetworks.Clear(); + forwardOptions.KnownProxies.Clear(); + app.UseForwardedHeaders(forwardOptions); + if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); @@ -174,13 +192,11 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) else { app.UseExceptionHandler("/Errors"); - // 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.UseSecurityHeaders(SecurityHeadersDefinitions - .GetHeaderPolicyCollection(env.IsDevelopment(), GetTypedConfiguration()) - .AddXssProtectionDisabled()); + .GetHeaderPolicyCollection(env.IsDevelopment(), GetTypedConfiguration())); + app.UseHsts(); app.UseCookiePolicy(new CookiePolicyOptions { @@ -195,16 +211,6 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.UseHttpsRedirection(); } - //For Azure AD redirect uri to remain https - var forwardOptions = new ForwardedHeadersOptions - { - ForwardedHeaders = ForwardedHeaders.All, - RequireHeaderSymmetry = false - }; - forwardOptions.KnownNetworks.Clear(); - forwardOptions.KnownProxies.Clear(); - app.UseForwardedHeaders(forwardOptions); - app.UseStaticFiles(); app.UseHealthChecks("/health"); @@ -282,7 +288,7 @@ private static void AddServices(IServiceCollection services, IConfiguration conf services.AddScoped(); services.AddScoped(); services.AddScoped(); - + services.AddSingleton(); services.AddSingleton(); services.AddSingleton();