diff --git a/Auth/LearningHub.Nhs.Auth/Configuration/WebSettings.cs b/Auth/LearningHub.Nhs.Auth/Configuration/WebSettings.cs
index 54dab61..4b4113d 100644
--- a/Auth/LearningHub.Nhs.Auth/Configuration/WebSettings.cs
+++ b/Auth/LearningHub.Nhs.Auth/Configuration/WebSettings.cs
@@ -56,5 +56,10 @@ public class WebSettings
/// Gets or sets the SupportFeedbackForm.
///
public string SupportFeedbackForm { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether IsPasswordUpdate.
+ ///
+ public bool IsPasswordUpdate { get; set; }
}
}
diff --git a/Auth/LearningHub.Nhs.Auth/Controllers/AccountController.cs b/Auth/LearningHub.Nhs.Auth/Controllers/AccountController.cs
index ff7b352..123fe1a 100644
--- a/Auth/LearningHub.Nhs.Auth/Controllers/AccountController.cs
+++ b/Auth/LearningHub.Nhs.Auth/Controllers/AccountController.cs
@@ -20,15 +20,11 @@
using LearningHub.Nhs.Auth.Models.Account;
using LearningHub.Nhs.Caching;
using LearningHub.Nhs.Models.Common;
- using LearningHub.Nhs.Models.Entities.Reporting;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
- using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
- using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
- using NHSUKViewComponents.Web.ViewModels;
///
/// Account Controller operations.
@@ -72,7 +68,7 @@ public AccountController(
this.authConfig = authConfig?.Value;
this.webSettings = webSettings;
this.logger = logger;
- }
+ }
///
/// Shows the Login page.
@@ -214,9 +210,9 @@ await this.UserService.AddLogonToUserHistory(
this.ModelState.AddModelError(string.Empty, loginResult.ErrorMessage);
}
- showFormWithError:
+showFormWithError:
- // something went wrong, show form with error
+// something went wrong, show form with error
var vm = await this.BuildLoginViewModelAsync(model);
if ((vm.ClientId == "learninghubwebclient") || (vm.ClientId == "learninghubadmin"))
{
@@ -268,6 +264,9 @@ public async Task Logout(LogoutInputModel model)
// delete local authentication cookie
await this.HttpContext.SignOutAsync();
+ // Delete the authentication cookie to ensure it is invalidated
+ this.HttpContext.Response.Cookies.Delete(".AspNetCore.Identity.Application");
+
// raise the logout event
await this.Events.RaiseAsync(new UserLogoutSuccessEvent(this.User.GetSubjectId(), this.User.GetDisplayName()));
@@ -296,7 +295,15 @@ public async Task Logout(LogoutInputModel model)
return this.SignOut(new AuthenticationProperties { RedirectUri = url }, vm.ExternalAuthenticationScheme);
}
- return this.View("LoggedOut", vm);
+ if (this.webSettings.IsPasswordUpdate)
+ {
+ var redirectUri = $"{this.webSettings.LearningHubWebClient}Home/ChangePasswordAcknowledgement";
+ return this.Redirect(redirectUri);
+ }
+ else
+ {
+ return this.View("LoggedOut", vm);
+ }
}
///
diff --git a/Auth/LearningHub.Nhs.Auth/Controllers/HomeController.cs b/Auth/LearningHub.Nhs.Auth/Controllers/HomeController.cs
index 7855fea..aa0937f 100644
--- a/Auth/LearningHub.Nhs.Auth/Controllers/HomeController.cs
+++ b/Auth/LearningHub.Nhs.Auth/Controllers/HomeController.cs
@@ -80,6 +80,27 @@ public async Task Error()
return this.View("Error");
}
+ ///
+ /// IsPasswordUpdateMethod.
+ ///
+ /// The Logout.
+ /// The .
+ [HttpGet]
+ public IActionResult SetIsPasswordUpdate(bool isLogout)
+ {
+ if (isLogout)
+ {
+ this.webSettings.IsPasswordUpdate = false;
+ }
+ else
+ {
+ this.webSettings.IsPasswordUpdate = true;
+ }
+
+ var redirectUri = $"{this.webSettings.LearningHubWebClient}Home/UserLogout";
+ return this.Redirect(redirectUri);
+ }
+
///
/// Shows the HealthCheck response.
///
diff --git a/Auth/LearningHub.Nhs.Auth/Helpers/InMemoryTicketStore.cs b/Auth/LearningHub.Nhs.Auth/Helpers/InMemoryTicketStore.cs
new file mode 100644
index 0000000..1bfa669
--- /dev/null
+++ b/Auth/LearningHub.Nhs.Auth/Helpers/InMemoryTicketStore.cs
@@ -0,0 +1,104 @@
+namespace LearningHub.Nhs.Auth.Helpers
+{
+ using System;
+ using System.Collections.Concurrent;
+ using System.Linq;
+ using System.Threading.Tasks;
+ using Microsoft.AspNetCore.Authentication;
+ using Microsoft.AspNetCore.Authentication.Cookies;
+
+ ///
+ /// Defines the .
+ ///
+ public class InMemoryTicketStore : ITicketStore
+ {
+ private readonly ConcurrentDictionary cache;
+
+ ///
+ /// Initializes a new instance of the class.
+ /// The InMemoryTicketStore.
+ ///
+ /// the cache.
+ public InMemoryTicketStore(ConcurrentDictionary cache)
+ {
+ this.cache = cache;
+ }
+
+ ///
+ /// The StoreAsync.
+ ///
+ /// The ticket.
+ /// The key.
+ public async Task StoreAsync(AuthenticationTicket ticket)
+ {
+ var ticketUserId = ticket.Principal.Claims.Where(c => c.Type == "sub")
+ .FirstOrDefault()
+ .Value;
+ var matchingAuthTicket = this.cache.Values.FirstOrDefault(
+ t => t.Principal.Claims.FirstOrDefault(
+ c => c.Type == "sub"
+ && c.Value == ticketUserId) != null);
+ if (matchingAuthTicket != null)
+ {
+ var cacheKey = this.cache.Where(
+ entry => entry.Value == matchingAuthTicket)
+ .Select(entry => entry.Key)
+ .FirstOrDefault();
+ this.cache.TryRemove(
+ cacheKey,
+ out _);
+ }
+
+ var key = Guid
+ .NewGuid()
+ .ToString();
+ await this.RenewAsync(
+ key,
+ ticket);
+ return key;
+ }
+
+ ///
+ /// The RenewAsync.
+ ///
+ /// The key.
+ /// The ticket.
+ /// The Task.
+ public Task RenewAsync(
+ string key,
+ AuthenticationTicket ticket)
+ {
+ this.cache.AddOrUpdate(
+ key,
+ ticket,
+ (_, _) => ticket);
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// The RetrieveAsync.
+ ///
+ /// The Key.
+ /// The Task.
+ public Task RetrieveAsync(string key)
+ {
+ this.cache.TryGetValue(
+ key,
+ out var ticket);
+ return Task.FromResult(ticket);
+ }
+
+ ///
+ /// The RemoveAsync.
+ ///
+ /// The key.
+ /// The Task.
+ public Task RemoveAsync(string key)
+ {
+ this.cache.TryRemove(
+ key,
+ out _);
+ return Task.CompletedTask;
+ }
+ }
+ }
diff --git a/Auth/LearningHub.Nhs.Auth/ServiceCollectionExtension.cs b/Auth/LearningHub.Nhs.Auth/ServiceCollectionExtension.cs
index 6aaf2f5..6268047 100644
--- a/Auth/LearningHub.Nhs.Auth/ServiceCollectionExtension.cs
+++ b/Auth/LearningHub.Nhs.Auth/ServiceCollectionExtension.cs
@@ -1,10 +1,12 @@
namespace LearningHub.Nhs.Auth
{
using System;
+ using System.Collections.Concurrent;
using System.Security.Cryptography.X509Certificates;
using Azure.Identity;
using IdentityServer4;
using LearningHub.Nhs.Auth.Configuration;
+ using LearningHub.Nhs.Auth.Helpers;
using LearningHub.Nhs.Auth.Middleware;
using LearningHub.Nhs.Caching;
using LearningHub.Nhs.Models.Enums;
@@ -70,7 +72,9 @@ public static void ConfigureServices(this IServiceCollection services, IConfigur
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
- }).AddCookie().AddOpenIdConnect(
+ })
+ .AddCookie()
+ .AddOpenIdConnect(
"oidc_oa",
options =>
{
diff --git a/Auth/LearningHub.Nhs.Auth/appsettings.json b/Auth/LearningHub.Nhs.Auth/appsettings.json
index f746802..c54a92d 100644
--- a/Auth/LearningHub.Nhs.Auth/appsettings.json
+++ b/Auth/LearningHub.Nhs.Auth/appsettings.json
@@ -39,9 +39,8 @@
"ElfhHub": "",
"Rcr": "",
"SupportForm": "https://support.learninghub.nhs.uk/support/tickets/new",
- "SupportFeedbackForm": "https://forms.office.com/e/C8tteweEhG"
-
-
+ "SupportFeedbackForm": "https://forms.office.com/e/C8tteweEhG",
+ "IsPasswordUpdate": "false"
},
"AllowOpenAthensDebug": false,
"OaLhClients": {
diff --git a/Auth/LearningHub.Nhs.Auth/package-lock.json b/Auth/LearningHub.Nhs.Auth/package-lock.json
index 3d0a1e4..22d15bb 100644
--- a/Auth/LearningHub.Nhs.Auth/package-lock.json
+++ b/Auth/LearningHub.Nhs.Auth/package-lock.json
@@ -16,7 +16,7 @@
"node": "^22"
},
"devDependencies": {
- "@babel/core": "^7.26.9",
+ "@babel/core": "^7.26.10",
"@babel/preset-env": "^7.26.9",
"babel-core": "^4.7.16",
"babel-loader": "^8.2.2",
@@ -25,7 +25,7 @@
"cross-env": "^7.0.3",
"css-loader": "^5.2.4",
"file-loader": "^6.2.0",
- "sass": "^1.85.1",
+ "sass": "^1.86.2",
"sass-loader": "^11.0.1",
"style-loader": "^2.0.0",
"ts-loader": "^9.5.2",
@@ -72,22 +72,22 @@
}
},
"node_modules/@babel/core": {
- "version": "7.26.9",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.9.tgz",
- "integrity": "sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw==",
+ "version": "7.26.10",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz",
+ "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.26.2",
- "@babel/generator": "^7.26.9",
+ "@babel/generator": "^7.26.10",
"@babel/helper-compilation-targets": "^7.26.5",
"@babel/helper-module-transforms": "^7.26.0",
- "@babel/helpers": "^7.26.9",
- "@babel/parser": "^7.26.9",
+ "@babel/helpers": "^7.26.10",
+ "@babel/parser": "^7.26.10",
"@babel/template": "^7.26.9",
- "@babel/traverse": "^7.26.9",
- "@babel/types": "^7.26.9",
+ "@babel/traverse": "^7.26.10",
+ "@babel/types": "^7.26.10",
"convert-source-map": "^2.0.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
@@ -103,14 +103,14 @@
}
},
"node_modules/@babel/generator": {
- "version": "7.26.9",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.9.tgz",
- "integrity": "sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg==",
+ "version": "7.26.10",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.10.tgz",
+ "integrity": "sha512-rRHT8siFIXQrAYOYqZQVsAr8vJ+cBNqcVAY6m5V8/4QqzaPl+zDBe6cLEPRDuNOUf3ww8RfJVlOyQMoSI+5Ang==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/parser": "^7.26.9",
- "@babel/types": "^7.26.9",
+ "@babel/parser": "^7.26.10",
+ "@babel/types": "^7.26.10",
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.25",
"jsesc": "^3.0.2"
@@ -341,27 +341,27 @@
}
},
"node_modules/@babel/helpers": {
- "version": "7.26.9",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.9.tgz",
- "integrity": "sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA==",
+ "version": "7.26.10",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.10.tgz",
+ "integrity": "sha512-UPYc3SauzZ3JGgj87GgZ89JVdC5dj0AoetR5Bw6wj4niittNyFh6+eOGonYvJ1ao6B8lEa3Q3klS7ADZ53bc5g==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/template": "^7.26.9",
- "@babel/types": "^7.26.9"
+ "@babel/types": "^7.26.10"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/parser": {
- "version": "7.26.9",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.9.tgz",
- "integrity": "sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==",
+ "version": "7.26.10",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.10.tgz",
+ "integrity": "sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/types": "^7.26.9"
+ "@babel/types": "^7.26.10"
},
"bin": {
"parser": "bin/babel-parser.js"
@@ -1378,17 +1378,17 @@
}
},
"node_modules/@babel/traverse": {
- "version": "7.26.9",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.9.tgz",
- "integrity": "sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg==",
+ "version": "7.26.10",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.10.tgz",
+ "integrity": "sha512-k8NuDrxr0WrPH5Aupqb2LCVURP/S0vBEn5mK6iH+GIYob66U5EtoZvcdudR2jQ4cmTwhEwW1DLB+Yyas9zjF6A==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.26.2",
- "@babel/generator": "^7.26.9",
- "@babel/parser": "^7.26.9",
+ "@babel/generator": "^7.26.10",
+ "@babel/parser": "^7.26.10",
"@babel/template": "^7.26.9",
- "@babel/types": "^7.26.9",
+ "@babel/types": "^7.26.10",
"debug": "^4.3.1",
"globals": "^11.1.0"
},
@@ -1397,9 +1397,9 @@
}
},
"node_modules/@babel/types": {
- "version": "7.26.9",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.9.tgz",
- "integrity": "sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==",
+ "version": "7.26.10",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.10.tgz",
+ "integrity": "sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -5877,9 +5877,9 @@
"license": "MIT"
},
"node_modules/sass": {
- "version": "1.85.1",
- "resolved": "https://registry.npmjs.org/sass/-/sass-1.85.1.tgz",
- "integrity": "sha512-Uk8WpxM5v+0cMR0XjX9KfRIacmSG86RH4DCCZjLU2rFh5tyutt9siAXJ7G+YfxQ99Q6wrRMbMlVl6KqUms71ag==",
+ "version": "1.86.2",
+ "resolved": "https://registry.npmjs.org/sass/-/sass-1.86.2.tgz",
+ "integrity": "sha512-Rpfn0zAIDqvnSb2DihJTDFjbhqLHu91Wqac9rxontWk7R+2txcPjuujMqu1eeoezh5kAblVCS5EdFdyr0Jmu+w==",
"dev": true,
"license": "MIT",
"dependencies": {
diff --git a/Auth/LearningHub.Nhs.Auth/package.json b/Auth/LearningHub.Nhs.Auth/package.json
index 85a5318..26249bf 100644
--- a/Auth/LearningHub.Nhs.Auth/package.json
+++ b/Auth/LearningHub.Nhs.Auth/package.json
@@ -26,7 +26,7 @@
"node": "^22"
},
"devDependencies": {
- "@babel/core": "^7.26.9",
+ "@babel/core": "^7.26.10",
"@babel/preset-env": "^7.26.9",
"babel-core": "^4.7.16",
"babel-loader": "^8.2.2",
@@ -35,7 +35,7 @@
"cross-env": "^7.0.3",
"css-loader": "^5.2.4",
"file-loader": "^6.2.0",
- "sass": "^1.85.1",
+ "sass": "^1.86.2",
"sass-loader": "^11.0.1",
"style-loader": "^2.0.0",
"ts-loader": "^9.5.2",
diff --git a/LearningHub.Nhs.UserApi.Repository.Interface/LH/IExternalSystemUserRepository.cs b/LearningHub.Nhs.UserApi.Repository.Interface/LH/IExternalSystemUserRepository.cs
index d84ded7..6f76875 100644
--- a/LearningHub.Nhs.UserApi.Repository.Interface/LH/IExternalSystemUserRepository.cs
+++ b/LearningHub.Nhs.UserApi.Repository.Interface/LH/IExternalSystemUserRepository.cs
@@ -1,6 +1,7 @@
namespace LearningHub.Nhs.UserApi.Repository.Interface.LH
{
using System.Threading.Tasks;
+ using elfhHub.Nhs.Models.Entities;
using LearningHub.Nhs.Models.Entities.External;
///
@@ -15,5 +16,12 @@ public interface IExternalSystemUserRepository : IGenericLHRepositoryThe external system id.
/// The .
Task GetByIdAsync(int userId, int externalSystemId);
+
+ ///
+ /// Create External system user.
+ ///
+ /// The userExternalSystem.
+ /// The .
+ Task CreateExternalSystemUserAsync(ExternalSystemUser userExternalSystem);
}
}
diff --git a/LearningHub.Nhs.UserApi.Repository/LH/ExternalSystemUserRepository.cs b/LearningHub.Nhs.UserApi.Repository/LH/ExternalSystemUserRepository.cs
index 0e03129..bc00c49 100644
--- a/LearningHub.Nhs.UserApi.Repository/LH/ExternalSystemUserRepository.cs
+++ b/LearningHub.Nhs.UserApi.Repository/LH/ExternalSystemUserRepository.cs
@@ -1,10 +1,15 @@
namespace LearningHub.Nhs.UserApi.Repository.LH
{
+ using System;
+ using System.Collections.Generic;
+ using System.Data;
using System.Linq;
using System.Threading.Tasks;
+ using elfhHub.Nhs.Models.Entities;
using LearningHub.Nhs.Models.Entities.External;
using LearningHub.Nhs.UserApi.Repository;
using LearningHub.Nhs.UserApi.Repository.Interface.LH;
+ using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
///
@@ -30,5 +35,22 @@ public async Task GetByIdAsync(int userId, int externalSyste
.AsNoTracking()
.FirstOrDefaultWithNoLockAsync();
}
+
+ ///
+ public async Task CreateExternalSystemUserAsync(ExternalSystemUser userExternalSystem)
+ {
+ try
+ {
+ var param0 = new SqlParameter("@p0", SqlDbType.Int) { Value = userExternalSystem.UserId };
+ var param1 = new SqlParameter("@p1", SqlDbType.Int) { Value = userExternalSystem.ExternalSystemId };
+ var param2 = new SqlParameter("@p2", SqlDbType.Int) { Value = userExternalSystem.UserId };
+ var param3 = new SqlParameter("@p3", SqlDbType.Int) { Value = this.TimezoneOffsetManager.UserTimezoneOffset ?? (object)DBNull.Value };
+ await this.DbContext.Database.ExecuteSqlRawAsync("[external].ExternalSystemUserCreate @p0, @p1, @p2, @p3", param0, param1, param2, param3);
+ }
+ catch (Exception ex)
+ {
+ throw new Exception(ex.Message);
+ }
+ }
}
}
diff --git a/LearningHub.Nhs.UserApi.Services/RegistrationService.cs b/LearningHub.Nhs.UserApi.Services/RegistrationService.cs
index ea3d67b..f3dccd3 100644
--- a/LearningHub.Nhs.UserApi.Services/RegistrationService.cs
+++ b/LearningHub.Nhs.UserApi.Services/RegistrationService.cs
@@ -185,7 +185,7 @@ public async Task LinkExistingUserToSso(int userId, int externalSystemId)
ExternalSystemId = externalSystemId,
};
- await this.externalSystemUserRepository.CreateAsync(userId, userExternalSystem);
+ await this.externalSystemUserRepository.CreateExternalSystemUserAsync(userExternalSystem);
}
///
@@ -336,7 +336,7 @@ public async Task RegisterUser(RegistrationRequestV
ExternalSystemId = registrationRequest.ExternalSystemId.Value,
};
- await this.externalSystemUserRepository.CreateAsync(userId, userExternalSystem);
+ await this.externalSystemUserRepository.CreateExternalSystemUserAsync(userExternalSystem);
}
if (registrationRequest.IsExternalUser == false)
diff --git a/LearningHub.Nhs.UserApi/Program.cs b/LearningHub.Nhs.UserApi/Program.cs
index e89e70b..8a6e0aa 100644
--- a/LearningHub.Nhs.UserApi/Program.cs
+++ b/LearningHub.Nhs.UserApi/Program.cs
@@ -10,6 +10,7 @@
var logger = NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
+var csp = "object-src 'none'; frame-ancestors 'none'; sandbox allow-forms allow-same-origin allow-scripts allow-popups; base-uri 'self';";
try
{
logger.Debug("Log Started");
@@ -36,6 +37,17 @@
c.SwaggerEndpoint($"/swagger/{app.Configuration["Swagger:Title"]}/swagger.json", app.Configuration["Swagger:Version"]);
});
+ app.Use(async (context, next) =>
+ {
+ context.Response.Headers.Add("content-security-policy", csp);
+ context.Response.Headers.Add("Referrer-Policy", "no-referrer");
+ context.Response.Headers.Add("Strict-Transport-Security", "max-age=31536000; includeSubDomains");
+ context.Response.Headers.Add("X-Content-Type-Options", "nosniff");
+ context.Response.Headers.Add("X-Frame-Options", "SAMEORIGIN");
+ context.Response.Headers.Add("X-XSS-protection", "0");
+ await next();
+ });
+
app.UseMiddleware();
app.UseEndpoints(endpoints => endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}"));