diff --git a/.github/workflows/continuous-integration-workflow.yml b/.github/workflows/continuous-integration-workflow.yml index baa6759..3293c61 100644 --- a/.github/workflows/continuous-integration-workflow.yml +++ b/.github/workflows/continuous-integration-workflow.yml @@ -18,7 +18,9 @@ jobs: dotnet-version: 8.0.x - name: Add Azure artifact - run: dotnet nuget add source 'https://pkgs.dev.azure.com/e-LfH/_packaging/LearningHubFeed/nuget/v3/index.json' --name 'LearningHubFeed' --username 'kevin.whittaker' --password ${{ secrets.AZURE_DEVOPS_PAT }} --store-password-in-clear-text + run: | + dotnet nuget remove source LearningHubFeed || true + dotnet nuget add source 'https://pkgs.dev.azure.com/e-LfH/_packaging/LearningHubFeed/nuget/v3/index.json' --name 'LearningHubFeed' --username 'kevin.whittaker' --password ${{ secrets.AZURE_DEVOPS_PAT }} --store-password-in-clear-text - name: Use NuGet 5.8 uses: nuget/setup-nuget@v1 diff --git a/Auth/LearningHub.Nhs.Auth.Tests/LearningHub.Nhs.Auth.Tests.csproj b/Auth/LearningHub.Nhs.Auth.Tests/LearningHub.Nhs.Auth.Tests.csproj index e52462d..4544d37 100644 --- a/Auth/LearningHub.Nhs.Auth.Tests/LearningHub.Nhs.Auth.Tests.csproj +++ b/Auth/LearningHub.Nhs.Auth.Tests/LearningHub.Nhs.Auth.Tests.csproj @@ -1,32 +1,27 @@ - - + net8.0 true false - x64 + x64 - - - - - - - - + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + \ No newline at end of file diff --git a/Auth/LearningHub.Nhs.Auth/Configuration/ServiceMappings.cs b/Auth/LearningHub.Nhs.Auth/Configuration/ServiceMappings.cs index 064aa10..79a6731 100644 --- a/Auth/LearningHub.Nhs.Auth/Configuration/ServiceMappings.cs +++ b/Auth/LearningHub.Nhs.Auth/Configuration/ServiceMappings.cs @@ -40,12 +40,22 @@ public static void AddServiceMappings(this IServiceCollection services, IConfigu ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator, }); + + services.AddHttpClient() + .ConfigurePrimaryHttpMessageHandler( + () => new HttpClientHandler + { + ServerCertificateCustomValidationCallback = + HttpClientHandler.DangerousAcceptAnyServerCertificateValidator, + }); } else { services.AddHttpClient(); + services.AddHttpClient(); } + services.AddScoped(); services.AddDistributedMemoryCache(); services.AddScoped(); services.AddTransient(); diff --git a/Auth/LearningHub.Nhs.Auth/Configuration/WebSettings.cs b/Auth/LearningHub.Nhs.Auth/Configuration/WebSettings.cs index 54dab61..0634fe6 100644 --- a/Auth/LearningHub.Nhs.Auth/Configuration/WebSettings.cs +++ b/Auth/LearningHub.Nhs.Auth/Configuration/WebSettings.cs @@ -56,5 +56,15 @@ 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; } + + /// + /// Gets or sets a value indicating whether gets or sets a value to Enable Moodle. + /// + public bool EnableMoodle { 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/Interfaces/IMoodleApiService.cs b/Auth/LearningHub.Nhs.Auth/Interfaces/IMoodleApiService.cs new file mode 100644 index 0000000..81a3adc --- /dev/null +++ b/Auth/LearningHub.Nhs.Auth/Interfaces/IMoodleApiService.cs @@ -0,0 +1,17 @@ +namespace LearningHub.Nhs.Auth.Interfaces +{ + using System.Threading.Tasks; + + /// + /// IMoodleApiService. + /// + public interface IMoodleApiService + { + /// + /// GetResourcesAsync. + /// + /// The current User Id. + /// A representing the result of the asynchronous operation. + Task GetMoodleUserIdByUsernameAsync(int currentUserId); + } +} diff --git a/Auth/LearningHub.Nhs.Auth/Interfaces/IMoodleHttpClient.cs b/Auth/LearningHub.Nhs.Auth/Interfaces/IMoodleHttpClient.cs new file mode 100644 index 0000000..1d711b8 --- /dev/null +++ b/Auth/LearningHub.Nhs.Auth/Interfaces/IMoodleHttpClient.cs @@ -0,0 +1,23 @@ +namespace LearningHub.Nhs.Auth.Interfaces +{ + using System.Net.Http; + using System.Threading.Tasks; + + /// + /// The Moodle Http Client interface. + /// + public interface IMoodleHttpClient + { + /// + /// The get cient async. + /// + /// The . + Task GetClient(); + + /// + /// GetDefaultParameters. + /// + /// defaultParameters. + string GetDefaultParameters(); + } +} diff --git a/Auth/LearningHub.Nhs.Auth/LearningHub.Nhs.Auth.csproj b/Auth/LearningHub.Nhs.Auth/LearningHub.Nhs.Auth.csproj index 15c031f..8fe3ee6 100644 --- a/Auth/LearningHub.Nhs.Auth/LearningHub.Nhs.Auth.csproj +++ b/Auth/LearningHub.Nhs.Auth/LearningHub.Nhs.Auth.csproj @@ -1,145 +1,133 @@ - - - - net8.0 - 00EF27C2-ECB6-4E37-A6B6-58E4E6189D0E - true - x64 - - - - - - - - - - - - - - - - - - - - - - - - - - - Never - - - - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - - - - - - - - - - - - - - - - - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - Always - - - Always - - - - - - - - - - - - - - + + + net8.0 + 00EF27C2-ECB6-4E37-A6B6-58E4E6189D0E + true + x64 + + + + + + + + + + + + + + + + + + + + + + + Never + + + + + true + PreserveNewest + + + true + PreserveNewest + + + true + PreserveNewest + + + true + PreserveNewest + + + true + PreserveNewest + + + true + PreserveNewest + + + true + PreserveNewest + + + true + PreserveNewest + + + true + PreserveNewest + + + true + PreserveNewest + + + true + PreserveNewest + + + true + PreserveNewest + + + true + PreserveNewest + + + + + + + + + + + + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + Always + + + Always + + + + + + + + + + + \ No newline at end of file diff --git a/Auth/LearningHub.Nhs.Auth/Models/MoodleUserResponseViewModel.cs b/Auth/LearningHub.Nhs.Auth/Models/MoodleUserResponseViewModel.cs new file mode 100644 index 0000000..fac745f --- /dev/null +++ b/Auth/LearningHub.Nhs.Auth/Models/MoodleUserResponseViewModel.cs @@ -0,0 +1,121 @@ +namespace LearningHub.Nhs.Auth.Models +{ + using System.Collections.Generic; + + /// + /// MoodleUserResponseViewModel. + /// + public class MoodleUserResponseViewModel + { + /// + /// Gets or sets the list of users. + /// + public List Users { get; set; } + + /// + /// Gets or sets the warnings. + /// + public List Warnings { get; set; } + + /// + /// MoodleUser. + /// + public class MoodleUser + { + /// + /// Gets or sets the user ID. + /// + public int Id { get; set; } + + /// + /// Gets or sets the username. + /// + public string Username { get; set; } + + /// + /// Gets or sets the first name. + /// + public string FirstName { get; set; } + + /// + /// Gets or sets the last name. + /// + public string LastName { get; set; } + + /// + /// Gets or sets the full name. + /// + public string FullName { get; set; } + + /// + /// Gets or sets the email. + /// + public string Email { get; set; } + + /// + /// Gets or sets the department. + /// + public string Department { get; set; } + + /// + /// Gets or sets the first access timestamp. + /// + public long FirstAccess { get; set; } + + /// + /// Gets or sets the last access timestamp. + /// + public long LastAccess { get; set; } + + /// + /// Gets or sets the authentication method. + /// + public string Auth { get; set; } + + /// + /// Gets or sets a value indicating whether the user is suspended. + /// + public bool Suspended { get; set; } + + /// + /// Gets or sets a value indicating whether the user is confirmed. + /// + public bool Confirmed { get; set; } + + /// + /// Gets or sets the language. + /// + public string Lang { get; set; } + + /// + /// Gets or sets the theme. + /// + public string Theme { get; set; } + + /// + /// Gets or sets the timezone. + /// + public string Timezone { get; set; } + + /// + /// Gets or sets the mail format. + /// + public int MailFormat { get; set; } + + /// + /// Gets or sets the forum tracking preference. + /// + public int TrackForums { get; set; } + + /// + /// Gets or sets the small profile image URL. + /// + public string ProfileImageUrlSmall { get; set; } + + /// + /// Gets or sets the profile image URL. + /// + public string ProfileImageUrl { get; set; } + } + } +} diff --git a/Auth/LearningHub.Nhs.Auth/NLog.config b/Auth/LearningHub.Nhs.Auth/NLog.config index eb67b60..a59da11 100644 --- a/Auth/LearningHub.Nhs.Auth/NLog.config +++ b/Auth/LearningHub.Nhs.Auth/NLog.config @@ -39,6 +39,10 @@ + + + + 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/Services/MoodleApiService.cs b/Auth/LearningHub.Nhs.Auth/Services/MoodleApiService.cs new file mode 100644 index 0000000..8edb52e --- /dev/null +++ b/Auth/LearningHub.Nhs.Auth/Services/MoodleApiService.cs @@ -0,0 +1,67 @@ +namespace LearningHub.Nhs.Auth.Services +{ + using System; + using System.Net.Http; + using System.Threading.Tasks; + using LearningHub.Nhs.Auth.Interfaces; + using LearningHub.Nhs.Auth.Models; + using Newtonsoft.Json; + + /// + /// MoodleApiService. + /// + public class MoodleApiService : IMoodleApiService + { + private readonly IMoodleHttpClient moodleHttpClient; + + /// + /// Initializes a new instance of the class. + /// + /// moodleHttpClient. + public MoodleApiService(IMoodleHttpClient moodleHttpClient) + { + this.moodleHttpClient = moodleHttpClient; + } + + /// + /// GetMoodleUserIdByUsernameAsync. + /// + /// current User Id. + /// UserId from Moodle. + public async Task GetMoodleUserIdByUsernameAsync(int currentUserId) + { + int moodleUserId = 0; + string additionalParameters = $"&criteria[0][key]=username&criteria[0][value]={currentUserId}"; + string defaultParameters = this.moodleHttpClient.GetDefaultParameters(); + + var client = await this.moodleHttpClient.GetClient(); + + string url = $"&wsfunction=core_user_get_users{additionalParameters}"; + + HttpResponseMessage response = await client.GetAsync("?" + defaultParameters + url); + if (response.IsSuccessStatusCode) + { + var result = response.Content.ReadAsStringAsync().Result; + var viewmodel = JsonConvert.DeserializeObject(result); + + if (viewmodel?.Users != null) + { + foreach (var user in viewmodel.Users) + { + if (user.Username == currentUserId.ToString()) + { + moodleUserId = user.Id; + } + } + } + } + else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized || + response.StatusCode == System.Net.HttpStatusCode.Forbidden) + { + throw new Exception("AccessDenied"); + } + + return moodleUserId; + } + } +} diff --git a/Auth/LearningHub.Nhs.Auth/Services/MoodleHttpClient.cs b/Auth/LearningHub.Nhs.Auth/Services/MoodleHttpClient.cs new file mode 100644 index 0000000..5538136 --- /dev/null +++ b/Auth/LearningHub.Nhs.Auth/Services/MoodleHttpClient.cs @@ -0,0 +1,87 @@ +namespace LearningHub.Nhs.Auth.Services +{ + using System; + using System.Net.Http; + using System.Net.Http.Headers; + using System.Threading.Tasks; + using LearningHub.Nhs.Auth.Interfaces; + using Microsoft.Extensions.Configuration; + + /// + /// The moodle http client. + /// + public class MoodleHttpClient : IMoodleHttpClient, IDisposable + { + private readonly HttpClient httpClient = new (); + private bool initialised = false; + private string moodleAPIBaseUrl; + private string moodleAPIMoodleWSRestFormat; + private string moodleAPIWSToken; + + /// + /// Initializes a new instance of the class. + /// + /// httpClient. + /// config. + public MoodleHttpClient(HttpClient httpClient, IConfiguration config) + { + this.httpClient = httpClient; + this.moodleAPIBaseUrl = config["MoodleAPIConfig:BaseUrl"]; + this.moodleAPIMoodleWSRestFormat = config["MoodleAPIConfig:MoodleWSRestFormat"]; + this.moodleAPIWSToken = config["MoodleAPIConfig:WSToken"]; + } + + /// + /// The Get Client method. + /// + /// The . + public async Task GetClient() + { + this.Initialise(this.moodleAPIBaseUrl); + return this.httpClient; + } + + /// + /// GetDefaultParameters. + /// + /// defaultParameters. + public string GetDefaultParameters() + { + string defaultParameters = $"wstoken={this.moodleAPIWSToken}" + + $"&moodlewsrestformat={this.moodleAPIMoodleWSRestFormat}"; + + return defaultParameters; + } + + /// + public void Dispose() + { + this.Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// The dispoase. + /// + /// disposing. + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + this.httpClient.Dispose(); + } + } + + private void Initialise(string httpClientUrl) + { + if (this.initialised == false) + { + this.httpClient.BaseAddress = new Uri(httpClientUrl); + this.httpClient.DefaultRequestHeaders.Accept.Clear(); + this.httpClient.DefaultRequestHeaders.Accept.Add( + new MediaTypeWithQualityHeaderValue("application/json")); + this.initialised = true; + } + } + } +} diff --git a/Auth/LearningHub.Nhs.Auth/UserServices/LearningHubProfileService.cs b/Auth/LearningHub.Nhs.Auth/UserServices/LearningHubProfileService.cs index 5a3a602..9175d60 100644 --- a/Auth/LearningHub.Nhs.Auth/UserServices/LearningHubProfileService.cs +++ b/Auth/LearningHub.Nhs.Auth/UserServices/LearningHubProfileService.cs @@ -6,6 +6,7 @@ using IdentityServer4.Extensions; using IdentityServer4.Models; using IdentityServer4.Services; + using LearningHub.Nhs.Auth.Configuration; using LearningHub.Nhs.Auth.Interfaces; using Microsoft.Extensions.Logging; @@ -14,19 +15,29 @@ /// public class LearningHubProfileService : IProfileService { + private readonly WebSettings webSettings; + /// /// Initializes a new instance of the class. /// /// /// The user service. /// + /// + /// The moodle api service. + /// /// /// The logger. /// - public LearningHubProfileService(IUserService userService, ILogger logger) + /// + /// The webSettings. + /// + public LearningHubProfileService(IUserService userService, IMoodleApiService moodleApiService, ILogger logger, WebSettings webSettings) { this.UserService = userService; + this.MoodleApiService = moodleApiService; this.Logger = logger; + this.webSettings = webSettings; } /// @@ -39,6 +50,11 @@ public LearningHubProfileService(IUserService userService, ILogger protected IUserService UserService { get; } + /// + /// Gets the moodle api service. + /// + protected IMoodleApiService MoodleApiService { get; } + /// /// The get profile data async. /// @@ -65,6 +81,12 @@ public async Task GetProfileDataAsync(ProfileDataRequestContext context) new Claim("elfh_userName", user.UserName), }; + if (this.webSettings.EnableMoodle) + { + var moodleUser = await this.MoodleApiService.GetMoodleUserIdByUsernameAsync(user.Id); + claims.Add(new Claim("preferred_username", moodleUser.ToString())); + } + if (context.Subject.HasClaim("openAthensUser", "true")) { claims.Add(new Claim("openAthensUser", "true")); diff --git a/Auth/LearningHub.Nhs.Auth/appsettings.json b/Auth/LearningHub.Nhs.Auth/appsettings.json index 1565fa4..f4daca9 100644 --- a/Auth/LearningHub.Nhs.Auth/appsettings.json +++ b/Auth/LearningHub.Nhs.Auth/appsettings.json @@ -1,362 +1,384 @@ { - "Environment": "", - "ApplicationInsights": { - "InstrumentationKey": "" - }, - "AzureDataProtection": { - "StorageConnectionString": "", - "StorageContainerName": "learning-hub-id4", - "VaultKeyIdentifier": "", - "TenantId": "", - "ClientId": "", - "ClientSecret": "" - }, - "OpenAthensConfig": { - "Authority": "", - "ClientId": "", - "ClientSecret": "", - "RedirectUri": "" - }, - "Logging": { - "LogLevel": { - "Default": "Trace", - "Microsoft": "Trace" - } - }, - "ConnectionStrings": { - "NLogDb": "", - "Redis": "" - }, - "AllowedHosts": "*", - "WebSettings": { - "BuildNumber": "NotSet", - "UserApiUrl": "", - "X509Certificate2Thumbprint": "", - "LearningHubAdminUrl": "", - "elfhClientMvcUrl": "", - "LearningHubWebClient": "", - "AuthClientIdentityKey": "", - "ElfhHub": "", - "Rcr": "", - "SupportForm": "https://support.learninghub.nhs.uk/support/tickets/new", - "SupportFeedbackForm": "https://forms.office.com/e/C8tteweEhG" - - - }, - "AllowOpenAthensDebug": false, - "OaLhClients": { - "4A49B728-487A-49DC-92EE-B8A848AE13F5": "", - "97859211-1DBF-4CCA-B9EA-37940A6442D8": "", - "B28B1A31-45C1-484B-8E83-9D57CC1C4C7B": "", - "3584C984-028C-4002-AA4B-58AF665AEBDD": "", - "LearningHubOAClient": "" - }, - "OaScopes": [ "" ], - "AuthKey": "", - "AuthOrigin": "", - "IdentityServerCertThumbprint": "", - "LearningHubAuthConfig": { - "LearningHubClientSecrets": { - "LearningHubWebClient": "" + "Environment": "", + "ApplicationInsights": { + "InstrumentationKey": "" }, - "AuthClientIdentityKey": "", - "AuthTimeout": 20, - "AuthClients": { - "learninghubadmin": { - "BaseUrl": "", - "ClientName": "", - "ClientSecret": "", - "AllowedGrantTypes": [ "" ], - "RedirectUris": [ "" ], - "PostLogoutUris": [ "" ], - "AllowedScopes": [ "", "", "", "", "" ], - "BackChannelLogoutSessionRequired": false, - "BackChannelLogoutUri": "", - "UpdateAccessTokenClaimsOnRefresh": false, - "RequireConsent": false, - "RequirePkce": false, - "AllowOfflineAccess": false - }, - "learninghubwebclient": { - "BaseUrl": "", - "ClientName": "", - "ClientSecret": "", - "AllowedGrantTypes": [ "" ], - "RedirectUris": [ "" ], - "PostLogoutUris": [ "" ], - "AllowedScopes": [ "", "", "", "", "" ], - "BackChannelLogoutSessionRequired": false, - "BackChannelLogoutUri": "", - "UpdateAccessTokenClaimsOnRefresh": false, - "RequireConsent": false, - "RequirePkce": false, - "AllowOfflineAccess": false - }, - "migrationTool": { - "BaseUrl": "", - "ClientName": "", - "ClientSecret": "", - "AllowedGrantTypes": [ "", "" ], - "RedirectUris": [], - "PostLogoutUris": [], - "AllowedScopes": [ "", "", "", "" ], - "BackChannelLogoutSessionRequired": false, - "BackChannelLogoutUri": "", - "UpdateAccessTokenClaimsOnRefresh": false, - "RequireConsent": false, - "RequirePkce": false, - "AllowOfflineAccess": false - }, - "learninghubwebclient_local": { - "BaseUrl": "", - "ClientName": "", - "ClientSecret": "", - "AllowedGrantTypes": [ "" ], - "RedirectUris": [ "" ], - "PostLogoutUris": [ "" ], - "AllowedScopes": [ "", "", "", "", "" ], - "BackChannelLogoutSessionRequired": false, - "BackChannelLogoutUri": "", - "UpdateAccessTokenClaimsOnRefresh": false, - "RequireConsent": false, - "RequirePkce": false, - "AllowOfflineAccess": false - }, - "learninghubadmin_local": { - "BaseUrl": "", - "ClientName": "", - "ClientSecret": "", - "AllowedGrantTypes": [ "" ], - "RedirectUris": [ "" ], - "PostLogoutUris": [ "" ], - "AllowedScopes": [ "", "", "", "", "" ], - "BackChannelLogoutSessionRequired": false, - "BackChannelLogoutUri": "", - "UpdateAccessTokenClaimsOnRefresh": false, - "RequireConsent": false, - "RequirePkce": false, - "AllowOfflineAccess": false - }, - "userprofileclient": { - "BaseUrl": "", - "ClientName": "", - "ClientSecret": "", - "AllowedGrantTypes": [ "" ], - "RedirectUris": [ "" ], - "PostLogoutUris": [ "" ], - "AllowedScopes": [ "", "", "", "", "", "" ], - "BackChannelLogoutSessionRequired": true, - "BackChannelLogoutUri": "", - "UpdateAccessTokenClaimsOnRefresh": true, - "RequireConsent": false, - "RequirePkce": true, - "AllowOfflineAccess": true - }, - "learninghubopenapi": { - "BaseUrl": "", - "ClientName": "", + "AzureDataProtection": { + "StorageConnectionString": "", + "StorageContainerName": "learning-hub-id4", + "VaultKeyIdentifier": "", + "TenantId": "", + "ClientId": "", + "ClientSecret": "" + }, + "OpenAthensConfig": { + "Authority": "", + "ClientId": "", "ClientSecret": "", - "AllowedGrantTypes": [ "" ], - "RedirectUris": [ "" ], - "PostLogoutUris": [ "" ], - "AllowedScopes": [ "", "", "", "", "" ], - "BackChannelLogoutSessionRequired": true, - "BackChannelLogoutUri": "", - "UpdateAccessTokenClaimsOnRefresh": true, - "RequireConsent": false, - "RequirePkce": true, - "AllowOfflineAccess": true - }, - "digitallearningsolutions": { + "RedirectUri": "" + }, + "Logging": { + "LogLevel": { + "Default": "Trace", + "Microsoft": "Trace" + } + }, + "ConnectionStrings": { + "NLogDb": "", + "Redis": "" + }, + "AllowedHosts": "*", + "WebSettings": { + "BuildNumber": "NotSet", + "UserApiUrl": "", + "X509Certificate2Thumbprint": "", + "LearningHubAdminUrl": "", + "elfhClientMvcUrl": "", + "LearningHubWebClient": "", + "AuthClientIdentityKey": "", + "ElfhHub": "", + "Rcr": "", + "SupportForm": "https://support.learninghub.nhs.uk/support/tickets/new", + "SupportFeedbackForm": "https://forms.office.com/e/C8tteweEhG", + "IsPasswordUpdate": "false", + "EnableMoodle": "false" + }, + "AllowOpenAthensDebug": false, + "OaLhClients": { + "4A49B728-487A-49DC-92EE-B8A848AE13F5": "", + "97859211-1DBF-4CCA-B9EA-37940A6442D8": "", + "B28B1A31-45C1-484B-8E83-9D57CC1C4C7B": "", + "3584C984-028C-4002-AA4B-58AF665AEBDD": "", + "LearningHubOAClient": "" + }, + "MoodleAPIConfig": { "BaseUrl": "", - "ClientName": "", - "ClientSecret": "", - "AllowedGrantTypes": [ "" ], - "RedirectUris": [ "" ], - "PostLogoutUris": [ "" ], - "AllowedScopes": [ "", "", "", "", "" ], - "BackChannelLogoutSessionRequired": true, - "BackChannelLogoutUri": "", - "UpdateAccessTokenClaimsOnRefresh": true, - "RequireConsent": false, - "RequirePkce": true, - "AllowOfflineAccess": true - } + "MoodleWSRestFormat": "json", + "WSToken": "" }, - "IdsClients": { - "eLfH": { - "ClientDescription": "e-Learning for Healthcare Hub", - "AuthSecret": "", - "ClientUrl": "", - "RedirectUris": [ "" ], - "PostLogoutUris": [ "", "" ], - "Scopes": [ "openathens" ], - "AuthMainTitle": "e-Learning for Healthcare Authentication", - "ClientLogoSrc": "/images/client-logos/elfh.svg", - "ClientLogoAltText": "e-Learning for Healthcare", - "ClientCssClass": "elfh-hub", - "ForgottenPasswordRelativeUrl": "forgotten-password", - "RegisterAccountRelativeUrl": "register", - "SupportUrl": "https://support.e-lfh.org.uk/", - "AllowRememberLogin": false - }, - "eIn": { - "ClientDescription": "eIntegrity", - "AuthSecret": "", - "ClientUrl": "", - "RedirectUris": [ "" ], - "PostLogoutUris": [ "" ], - "AuthMainTitle": "e-Integrity Authentication", - "ClientLogoSrc": "/images/client-logos/eInt.svg", - "ClientLogoAltText": "eIntegrity", - "ClientCssClass": "eIntegrity", - "ForgottenPasswordRelativeUrl": "forgotten-password", - "UseRegister": false, - "RegisterAccountRelativeUrl": "", - "SupportUrl": "https://support.e-lfh.org.uk/", - "AllowRememberLogin": false - }, - "etft": { - "ClientDescription": "ETFT Educator Hub", - "AuthSecret": "", - "ClientUrl": "", - "RedirectUris": [ "" ], - "PostLogoutUris": [ "" ], - "AuthMainTitle": "Educator Hub Authentication", - "ClientLogoSrc": "/images/client-logos/etft-educator-hub.png", - "ClientLogoAltText": "ETFT Educator Hub", - "ClientCssClass": "etft", - "ForgottenPasswordRelativeUrl": "forgotten-password", - "RegisterAccountRelativeUrl": "register", - "SupportUrl": "https://support.e-lfh.org.uk/", - "AllowRememberLogin": false - }, - "minded": { - "ClientDescription": "MindEd", - "AuthSecret": "", - "ClientUrl": "", - "RedirectUris": [ "" ], - "PostLogoutUris": [ "" ], - "AuthMainTitle": "MindEd Authentication", - "ClientLogoSrc": "/images/client-logos/minded.svg", - "ClientLogoAltText": "MindEd", - "ClientCssClass": "minded", - "ForgottenPasswordRelativeUrl": "forgotten-password", - "RegisterAccountRelativeUrl": "register", - "SupportUrl": "https://support.e-lfh.org.uk/", - "AllowRememberLogin": false - }, - "dismat": { - "ClientDescription": "Disability Matters", - "AuthSecret": "", - "ClientUrl": "", - "RedirectUris": [ "" ], - "PostLogoutUris": [ "" ], - "AuthMainTitle": "Disability Matters Authentication", - "ClientLogoSrc": "/images/client-logos/disability-matters.png", - "ClientLogoAltText": "Disability Matters", - "ClientCssClass": "disability-matters", - "ForgottenPasswordRelativeUrl": "forgotten-password", - "RegisterAccountRelativeUrl": "register", - "SupportUrl": "https://support.e-lfh.org.uk/", - "AllowRememberLogin": false - }, - "popwell": { - "ClientDescription": "Population Wellbeing Portal", - "AuthSecret": "", - "ClientUrl": "", - "RedirectUris": [ "" ], - "PostLogoutUris": [ "" ], - "AuthMainTitle": "Population Wellbeing Authentication", - "ClientLogoSrc": "/images/client-logos/population-wellbeing.png", - "ClientLogoAltText": "Population Wellbeing Portal", - "ClientCssClass": "population-wellbeing", - "ForgottenPasswordRelativeUrl": "forgotten-password", - "RegisterAccountRelativeUrl": "register", - "SupportUrl": "https://support.e-lfh.org.uk/", - "AllowRememberLogin": false - }, - "volpass": { - "ClientDescription": "Volunteer Passport", - "AuthSecret": "", - "ClientUrl": "", - "RedirectUris": [ "" ], - "PostLogoutUris": [ "" ], - "AuthMainTitle": "VLP Authentication", - "ClientLogoSrc": "/images/client-logos/volpass.png", - "ClientLogoAltText": "Volunteers Passport", - "ClientCssClass": "vlp", - "ForgottenPasswordRelativeUrl": "forgotten-password", - "RegisterAccountRelativeUrl": "register", - "SupportUrl": "https://support.e-lfh.org.uk/", - "AllowRememberLogin": false - }, - "carers": { - "ClientDescription": "Supporting Unpaid Carers", - "AuthSecret": "", - "ClientUrl": "", - "RedirectUris": [ "" ], - "PostLogoutUris": [ "" ], - "AuthMainTitle": "Supporting Unpaid Carers Authentication", - "ClientLogoSrc": "/images/client-logos/carers.svg", - "ClientLogoAltText": "Supporting Unpaid Carers", - "ClientCssClass": "carers", - "ForgottenPasswordRelativeUrl": "forgotten-password", - "RegisterAccountRelativeUrl": "register", - "SupportUrl": "https://support.e-lfh.org.uk/", - "AllowRememberLogin": false - }, - "learninghubadmin": { - "ClientDescription": "Learning Hub Admin App", - "AuthSecret": "", - "ClientUrl": "", - "RedirectUris": [], - "PostLogoutUris": [], - "AuthMainTitle": "Learning Hub Authentication", - "ClientLogoSrc": "/images/client-logos/learningHubAdmin.svg", - "ClientLogoUrl": "https://www.nhs.uk/", - "ClientLogoAltText": "Learning Hub Administration", - "ClientCssClass": "learning-hub", - "UseForgottenPassword": false, - "UseRegister": false, - "UseSupport": false, - "AllowRememberLogin": false, - "LayoutPath": "/Views/Shared/LearningHub/_Layout.cshtml" - }, - "learninghubwebclient": { - "ClientDescription": "Learning Hub", - "AuthSecret": "", - "ClientUrl": "", - "ForgottenPasswordRelativeUrl": "forgotten-password", - "RegisterAccountRelativeUrl": "registration/create-an-account", - "RedirectUris": [], - "PostLogoutUris": [], - "AuthMainTitle": "Learning Hub", - "ClientLogoSrc": "/images/client-logos/nhs-learning-hub-beta.png", - "ClientLogoUrl": "https://www.nhs.uk/", - "ClientLogoAltText": "Learning Hub", - "ClientCssClass": "learning-hub", - "UseForgottenPassword": true, - "UseRegister": true, - "UseSupport": false, - "AllowRememberLogin": false, - "LayoutPath": "/Views/Shared/LearningHub/_Layout.cshtml" - }, - "digitallearningsolutions": { - "ClientDescription": "Learning Hub", - "ClientUrl": "", - "RedirectUris": [], - "PostLogoutUris": [], - "AuthMainTitle": "Digital Learning Solutions Authentication", - "ClientLogoSrc": "/images/client-logos/dls.svg", - "ClientLogoAltText": "Digital Learning Solutions", - "ClientCssClass": "learning-hub", - "ForgottenPasswordRelativeUrl": "forgotten-password", - "RegisterAccountRelativeUrl": "register", - "SupportUrl": "https://support.e-lfh.org.uk/", - "AllowRememberLogin": false, - "UseRegister": false - } + "OaScopes": [ "" ], + "AuthKey": "", + "AuthOrigin": "", + "IdentityServerCertThumbprint": "", + "LearningHubAuthConfig": { + "LearningHubClientSecrets": { + "LearningHubWebClient": "" + }, + "AuthClientIdentityKey": "", + "AuthTimeout": 20, + "AuthClients": { + "learninghubadmin": { + "BaseUrl": "", + "ClientName": "", + "ClientSecret": "", + "AllowedGrantTypes": [ "" ], + "RedirectUris": [ "" ], + "PostLogoutUris": [ "" ], + "AllowedScopes": [ "", "", "", "", "" ], + "BackChannelLogoutSessionRequired": false, + "BackChannelLogoutUri": "", + "UpdateAccessTokenClaimsOnRefresh": false, + "RequireConsent": false, + "RequirePkce": false, + "AllowOfflineAccess": false + }, + "learninghubwebclient": { + "BaseUrl": "", + "ClientName": "", + "ClientSecret": "", + "AllowedGrantTypes": [ "" ], + "RedirectUris": [ "" ], + "PostLogoutUris": [ "" ], + "AllowedScopes": [ "", "", "", "", "" ], + "BackChannelLogoutSessionRequired": false, + "BackChannelLogoutUri": "", + "UpdateAccessTokenClaimsOnRefresh": false, + "RequireConsent": false, + "RequirePkce": false, + "AllowOfflineAccess": false + }, + "migrationTool": { + "BaseUrl": "", + "ClientName": "", + "ClientSecret": "", + "AllowedGrantTypes": [ "", "" ], + "RedirectUris": [], + "PostLogoutUris": [], + "AllowedScopes": [ "", "", "", "" ], + "BackChannelLogoutSessionRequired": false, + "BackChannelLogoutUri": "", + "UpdateAccessTokenClaimsOnRefresh": false, + "RequireConsent": false, + "RequirePkce": false, + "AllowOfflineAccess": false + }, + "learninghubwebclient_local": { + "BaseUrl": "", + "ClientName": "", + "ClientSecret": "", + "AllowedGrantTypes": [ "" ], + "RedirectUris": [ "" ], + "PostLogoutUris": [ "" ], + "AllowedScopes": [ "", "", "", "", "" ], + "BackChannelLogoutSessionRequired": false, + "BackChannelLogoutUri": "", + "UpdateAccessTokenClaimsOnRefresh": false, + "RequireConsent": false, + "RequirePkce": false, + "AllowOfflineAccess": false + }, + "learninghubadmin_local": { + "BaseUrl": "", + "ClientName": "", + "ClientSecret": "", + "AllowedGrantTypes": [ "" ], + "RedirectUris": [ "" ], + "PostLogoutUris": [ "" ], + "AllowedScopes": [ "", "", "", "", "" ], + "BackChannelLogoutSessionRequired": false, + "BackChannelLogoutUri": "", + "UpdateAccessTokenClaimsOnRefresh": false, + "RequireConsent": false, + "RequirePkce": false, + "AllowOfflineAccess": false + }, + "userprofileclient": { + "BaseUrl": "", + "ClientName": "", + "ClientSecret": "", + "AllowedGrantTypes": [ "" ], + "RedirectUris": [ "" ], + "PostLogoutUris": [ "" ], + "AllowedScopes": [ "", "", "", "", "", "" ], + "BackChannelLogoutSessionRequired": true, + "BackChannelLogoutUri": "", + "UpdateAccessTokenClaimsOnRefresh": true, + "RequireConsent": false, + "RequirePkce": true, + "AllowOfflineAccess": true + }, + "learninghubopenapi": { + "BaseUrl": "", + "ClientName": "", + "ClientSecret": "", + "AllowedGrantTypes": [ "" ], + "RedirectUris": [ "" ], + "PostLogoutUris": [ "" ], + "AllowedScopes": [ "", "", "", "", "" ], + "BackChannelLogoutSessionRequired": true, + "BackChannelLogoutUri": "", + "UpdateAccessTokenClaimsOnRefresh": true, + "RequireConsent": false, + "RequirePkce": true, + "AllowOfflineAccess": true + }, + "digitallearningsolutions": { + "BaseUrl": "", + "ClientName": "", + "ClientSecret": "", + "AllowedGrantTypes": [ "" ], + "RedirectUris": [ "" ], + "PostLogoutUris": [ "" ], + "AllowedScopes": [ "", "", "", "", "" ], + "BackChannelLogoutSessionRequired": true, + "BackChannelLogoutUri": "", + "UpdateAccessTokenClaimsOnRefresh": true, + "RequireConsent": false, + "RequirePkce": true, + "AllowOfflineAccess": true + }, + "moodle": { + "BaseUrl": "", + "ClientName": "", + "ClientSecret": "", + "AllowedGrantTypes": [ "authorization_code" ], + "RedirectUris": [ "/auth/oidc/" ], + "PostLogoutUris": [ "/login/logout.php" ], + "AllowedScopes": [ "openid", "profile", "learninghubapi", "userapi", "roles", "learningcredentialsapi" ], + "BackChannelLogoutSessionRequired": true, + "BackChannelLogoutUri": "/login/logout.php", + "FrontChannelLogoutSessionRequired": true, + "FrontChannelLogoutUri": "/login/logout.php", + "UpdateAccessTokenClaimsOnRefresh": true, + "RequireConsent": false, + "RequirePkce": false, + "AllowOfflineAccess": true + } + }, + "IdsClients": { + "eLfH": { + "ClientDescription": "e-Learning for Healthcare Hub", + "AuthSecret": "", + "ClientUrl": "", + "RedirectUris": [ "" ], + "PostLogoutUris": [ "", "" ], + "Scopes": [ "openathens" ], + "AuthMainTitle": "e-Learning for Healthcare Authentication", + "ClientLogoSrc": "/images/client-logos/elfh.svg", + "ClientLogoAltText": "e-Learning for Healthcare", + "ClientCssClass": "elfh-hub", + "ForgottenPasswordRelativeUrl": "forgotten-password", + "RegisterAccountRelativeUrl": "register", + "SupportUrl": "https://support.e-lfh.org.uk/", + "AllowRememberLogin": false + }, + "eIn": { + "ClientDescription": "eIntegrity", + "AuthSecret": "", + "ClientUrl": "", + "RedirectUris": [ "" ], + "PostLogoutUris": [ "" ], + "AuthMainTitle": "e-Integrity Authentication", + "ClientLogoSrc": "/images/client-logos/eInt.svg", + "ClientLogoAltText": "eIntegrity", + "ClientCssClass": "eIntegrity", + "ForgottenPasswordRelativeUrl": "forgotten-password", + "UseRegister": false, + "RegisterAccountRelativeUrl": "", + "SupportUrl": "https://support.e-lfh.org.uk/", + "AllowRememberLogin": false + }, + "etft": { + "ClientDescription": "ETFT Educator Hub", + "AuthSecret": "", + "ClientUrl": "", + "RedirectUris": [ "" ], + "PostLogoutUris": [ "" ], + "AuthMainTitle": "Educator Hub Authentication", + "ClientLogoSrc": "/images/client-logos/etft-educator-hub.png", + "ClientLogoAltText": "ETFT Educator Hub", + "ClientCssClass": "etft", + "ForgottenPasswordRelativeUrl": "forgotten-password", + "RegisterAccountRelativeUrl": "register", + "SupportUrl": "https://support.e-lfh.org.uk/", + "AllowRememberLogin": false + }, + "minded": { + "ClientDescription": "MindEd", + "AuthSecret": "", + "ClientUrl": "", + "RedirectUris": [ "" ], + "PostLogoutUris": [ "" ], + "AuthMainTitle": "MindEd Authentication", + "ClientLogoSrc": "/images/client-logos/minded.svg", + "ClientLogoAltText": "MindEd", + "ClientCssClass": "minded", + "ForgottenPasswordRelativeUrl": "forgotten-password", + "RegisterAccountRelativeUrl": "register", + "SupportUrl": "https://support.e-lfh.org.uk/", + "AllowRememberLogin": false + }, + "dismat": { + "ClientDescription": "Disability Matters", + "AuthSecret": "", + "ClientUrl": "", + "RedirectUris": [ "" ], + "PostLogoutUris": [ "" ], + "AuthMainTitle": "Disability Matters Authentication", + "ClientLogoSrc": "/images/client-logos/disability-matters.png", + "ClientLogoAltText": "Disability Matters", + "ClientCssClass": "disability-matters", + "ForgottenPasswordRelativeUrl": "forgotten-password", + "RegisterAccountRelativeUrl": "register", + "SupportUrl": "https://support.e-lfh.org.uk/", + "AllowRememberLogin": false + }, + "popwell": { + "ClientDescription": "Population Wellbeing Portal", + "AuthSecret": "", + "ClientUrl": "", + "RedirectUris": [ "" ], + "PostLogoutUris": [ "" ], + "AuthMainTitle": "Population Wellbeing Authentication", + "ClientLogoSrc": "/images/client-logos/population-wellbeing.png", + "ClientLogoAltText": "Population Wellbeing Portal", + "ClientCssClass": "population-wellbeing", + "ForgottenPasswordRelativeUrl": "forgotten-password", + "RegisterAccountRelativeUrl": "register", + "SupportUrl": "https://support.e-lfh.org.uk/", + "AllowRememberLogin": false + }, + "volpass": { + "ClientDescription": "Volunteer Passport", + "AuthSecret": "", + "ClientUrl": "", + "RedirectUris": [ "" ], + "PostLogoutUris": [ "" ], + "AuthMainTitle": "VLP Authentication", + "ClientLogoSrc": "/images/client-logos/volpass.png", + "ClientLogoAltText": "Volunteers Passport", + "ClientCssClass": "vlp", + "ForgottenPasswordRelativeUrl": "forgotten-password", + "RegisterAccountRelativeUrl": "register", + "SupportUrl": "https://support.e-lfh.org.uk/", + "AllowRememberLogin": false + }, + "carers": { + "ClientDescription": "Supporting Unpaid Carers", + "AuthSecret": "", + "ClientUrl": "", + "RedirectUris": [ "" ], + "PostLogoutUris": [ "" ], + "AuthMainTitle": "Supporting Unpaid Carers Authentication", + "ClientLogoSrc": "/images/client-logos/carers.svg", + "ClientLogoAltText": "Supporting Unpaid Carers", + "ClientCssClass": "carers", + "ForgottenPasswordRelativeUrl": "forgotten-password", + "RegisterAccountRelativeUrl": "register", + "SupportUrl": "https://support.e-lfh.org.uk/", + "AllowRememberLogin": false + }, + "learninghubadmin": { + "ClientDescription": "Learning Hub Admin App", + "AuthSecret": "", + "ClientUrl": "", + "RedirectUris": [], + "PostLogoutUris": [], + "AuthMainTitle": "Learning Hub Authentication", + "ClientLogoSrc": "/images/client-logos/learningHubAdmin.svg", + "ClientLogoUrl": "https://www.nhs.uk/", + "ClientLogoAltText": "Learning Hub Administration", + "ClientCssClass": "learning-hub", + "UseForgottenPassword": false, + "UseRegister": false, + "UseSupport": false, + "AllowRememberLogin": false, + "LayoutPath": "/Views/Shared/LearningHub/_Layout.cshtml" + }, + "learninghubwebclient": { + "ClientDescription": "Learning Hub", + "AuthSecret": "", + "ClientUrl": "", + "ForgottenPasswordRelativeUrl": "forgotten-password", + "RegisterAccountRelativeUrl": "registration/create-an-account", + "RedirectUris": [], + "PostLogoutUris": [], + "AuthMainTitle": "Learning Hub", + "ClientLogoSrc": "/images/client-logos/nhs-learning-hub-beta.png", + "ClientLogoUrl": "https://www.nhs.uk/", + "ClientLogoAltText": "Learning Hub", + "ClientCssClass": "learning-hub", + "UseForgottenPassword": true, + "UseRegister": true, + "UseSupport": false, + "AllowRememberLogin": false, + "LayoutPath": "/Views/Shared/LearningHub/_Layout.cshtml" + }, + "digitallearningsolutions": { + "ClientDescription": "Learning Hub", + "ClientUrl": "", + "RedirectUris": [], + "PostLogoutUris": [], + "AuthMainTitle": "Digital Learning Solutions Authentication", + "ClientLogoSrc": "/images/client-logos/dls.svg", + "ClientLogoAltText": "Digital Learning Solutions", + "ClientCssClass": "learning-hub", + "ForgottenPasswordRelativeUrl": "forgotten-password", + "RegisterAccountRelativeUrl": "register", + "SupportUrl": "https://support.e-lfh.org.uk/", + "AllowRememberLogin": false, + "UseRegister": false + } + } } - } } \ No newline at end of file diff --git a/Auth/LearningHub.Nhs.Auth/web.config b/Auth/LearningHub.Nhs.Auth/web.config new file mode 100644 index 0000000..0cd2434 --- /dev/null +++ b/Auth/LearningHub.Nhs.Auth/web.config @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Directory.Build.props b/Directory.Build.props index 041b430..d153dde 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -4,7 +4,7 @@ $(SolutionDir)StyleCop.ruleset - + \ No newline at end of file diff --git a/Directory.Packages.props b/Directory.Packages.props new file mode 100644 index 0000000..c94d0a7 --- /dev/null +++ b/Directory.Packages.props @@ -0,0 +1,49 @@ + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Hee.UserProfile.Database/Hee.UserProfile.Database.sqlproj b/Hee.UserProfile.Database/Hee.UserProfile.Database.sqlproj index b8cf3b5..df6c02e 100644 --- a/Hee.UserProfile.Database/Hee.UserProfile.Database.sqlproj +++ b/Hee.UserProfile.Database/Hee.UserProfile.Database.sqlproj @@ -16,7 +16,7 @@ 1033, CI BySchemaAndSchemaType True - v4.5.2 + v4.8 CS Properties False 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.Interface/LearningHub.Nhs.UserApi.Repository.Interface.csproj b/LearningHub.Nhs.UserApi.Repository.Interface/LearningHub.Nhs.UserApi.Repository.Interface.csproj index fc69964..60f0b5d 100644 --- a/LearningHub.Nhs.UserApi.Repository.Interface/LearningHub.Nhs.UserApi.Repository.Interface.csproj +++ b/LearningHub.Nhs.UserApi.Repository.Interface/LearningHub.Nhs.UserApi.Repository.Interface.csproj @@ -1,23 +1,19 @@ - - + net8.0 true false - x64 + x64 - - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + \ No newline at end of file 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.Repository/LearningHub.Nhs.UserApi.Repository.csproj b/LearningHub.Nhs.UserApi.Repository/LearningHub.Nhs.UserApi.Repository.csproj index 4644295..7d254b8 100644 --- a/LearningHub.Nhs.UserApi.Repository/LearningHub.Nhs.UserApi.Repository.csproj +++ b/LearningHub.Nhs.UserApi.Repository/LearningHub.Nhs.UserApi.Repository.csproj @@ -1,25 +1,21 @@ - - + net8.0 true false - x64 + x64 - - - - - - + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + \ No newline at end of file diff --git a/LearningHub.Nhs.UserApi.Services.Interface/LearningHub.Nhs.UserAPI.Services.Interface.csproj b/LearningHub.Nhs.UserApi.Services.Interface/LearningHub.Nhs.UserAPI.Services.Interface.csproj index fc69964..60f0b5d 100644 --- a/LearningHub.Nhs.UserApi.Services.Interface/LearningHub.Nhs.UserAPI.Services.Interface.csproj +++ b/LearningHub.Nhs.UserApi.Services.Interface/LearningHub.Nhs.UserAPI.Services.Interface.csproj @@ -1,23 +1,19 @@ - - + net8.0 true false - x64 + x64 - - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + \ No newline at end of file diff --git a/LearningHub.Nhs.UserApi.Services.UnitTests/LearningHub.Nhs.UserApi.Services.UnitTests.csproj b/LearningHub.Nhs.UserApi.Services.UnitTests/LearningHub.Nhs.UserApi.Services.UnitTests.csproj index 78785b5..2bcf2e7 100644 --- a/LearningHub.Nhs.UserApi.Services.UnitTests/LearningHub.Nhs.UserApi.Services.UnitTests.csproj +++ b/LearningHub.Nhs.UserApi.Services.UnitTests/LearningHub.Nhs.UserApi.Services.UnitTests.csproj @@ -1,37 +1,33 @@ - - + net8.0 - true + true enable enable - x64 + x64 false - - - - - - - - - - - + + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all - - - + \ No newline at end of file diff --git a/LearningHub.Nhs.UserApi.Services/LearningHub.Nhs.UserApi.Services.csproj b/LearningHub.Nhs.UserApi.Services/LearningHub.Nhs.UserApi.Services.csproj index 0b91349..a81d32a 100644 --- a/LearningHub.Nhs.UserApi.Services/LearningHub.Nhs.UserApi.Services.csproj +++ b/LearningHub.Nhs.UserApi.Services/LearningHub.Nhs.UserApi.Services.csproj @@ -1,27 +1,24 @@ - - + net8.0 true false - x64 + x64 - - - - - - + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - - + \ No newline at end of file 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.Shared/LearningHub.Nhs.UserApi.Shared.csproj b/LearningHub.Nhs.UserApi.Shared/LearningHub.Nhs.UserApi.Shared.csproj index 149be25..04b48b4 100644 --- a/LearningHub.Nhs.UserApi.Shared/LearningHub.Nhs.UserApi.Shared.csproj +++ b/LearningHub.Nhs.UserApi.Shared/LearningHub.Nhs.UserApi.Shared.csproj @@ -1,19 +1,16 @@ - - + net8.0 true false - x64 + x64 - - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + \ No newline at end of file diff --git a/LearningHub.Nhs.UserApi.UnitTests/LearningHub.Nhs.UserApi.UnitTests.csproj b/LearningHub.Nhs.UserApi.UnitTests/LearningHub.Nhs.UserApi.UnitTests.csproj index fda3b53..4eb125a 100644 --- a/LearningHub.Nhs.UserApi.UnitTests/LearningHub.Nhs.UserApi.UnitTests.csproj +++ b/LearningHub.Nhs.UserApi.UnitTests/LearningHub.Nhs.UserApi.UnitTests.csproj @@ -1,37 +1,32 @@ - - + net8.0 - true + true enable enable - x64 + x64 false - - - - - - - + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all - - - - + \ No newline at end of file diff --git a/LearningHub.Nhs.UserApi.sln b/LearningHub.Nhs.UserApi.sln index adb65c7..9775d9c 100644 --- a/LearningHub.Nhs.UserApi.sln +++ b/LearningHub.Nhs.UserApi.sln @@ -6,6 +6,8 @@ MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{683CA47A-9041-4CB9-B436-CD20BD40EB34}" ProjectSection(SolutionItems) = preProject Directory.Build.props = Directory.Build.props + Directory.Packages.props = Directory.Packages.props + nuget.config = nuget.config StyleCop.json = StyleCop.json StyleCop.ruleset = StyleCop.ruleset EndProjectSection diff --git a/LearningHub.Nhs.UserApi/LearningHub.Nhs.UserApi.csproj b/LearningHub.Nhs.UserApi/LearningHub.Nhs.UserApi.csproj index 4c32a0f..f98d757 100644 --- a/LearningHub.Nhs.UserApi/LearningHub.Nhs.UserApi.csproj +++ b/LearningHub.Nhs.UserApi/LearningHub.Nhs.UserApi.csproj @@ -1,43 +1,37 @@ - - + net8.0 InProcess true - x64 + x64 - LearningHub.Nhs.UserApi.xml - - Always - - - - - - - - - - + + + + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + - @@ -45,12 +39,14 @@ - Never - - + + + + + \ No newline at end of file diff --git a/LearningHub.Nhs.UserApi/Program.cs b/LearningHub.Nhs.UserApi/Program.cs index e89e70b..c82ae49 100644 --- a/LearningHub.Nhs.UserApi/Program.cs +++ b/LearningHub.Nhs.UserApi/Program.cs @@ -10,6 +10,8 @@ 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 +38,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?}")); diff --git a/LearningHub.Nhs.UserApi/web.config b/LearningHub.Nhs.UserApi/web.config new file mode 100644 index 0000000..f1d8e42 --- /dev/null +++ b/LearningHub.Nhs.UserApi/web.config @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nuget.config b/nuget.config new file mode 100644 index 0000000..4b5a055 --- /dev/null +++ b/nuget.config @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file