diff --git a/LearningHub.Nhs.WebUI/Helpers/InMemoryTicketStore.cs b/LearningHub.Nhs.WebUI/Helpers/InMemoryTicketStore.cs new file mode 100644 index 000000000..4d17cc5b7 --- /dev/null +++ b/LearningHub.Nhs.WebUI/Helpers/InMemoryTicketStore.cs @@ -0,0 +1,104 @@ +namespace LearningHub.Nhs.WebUI.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; + } + } +} \ No newline at end of file diff --git a/LearningHub.Nhs.WebUI/Startup/AuthenticationConfiguration.cs b/LearningHub.Nhs.WebUI/Startup/AuthenticationConfiguration.cs index 40caab241..bbd39d9e2 100644 --- a/LearningHub.Nhs.WebUI/Startup/AuthenticationConfiguration.cs +++ b/LearningHub.Nhs.WebUI/Startup/AuthenticationConfiguration.cs @@ -1,12 +1,14 @@ namespace LearningHub.Nhs.WebUI.Startup { using System; + using System.Collections.Concurrent; using System.Linq; using System.Threading.Tasks; using IdentityModel; using LearningHub.Nhs.Caching; using LearningHub.Nhs.WebUI.Configuration; using LearningHub.Nhs.WebUI.Handlers; + using LearningHub.Nhs.WebUI.Helpers; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.OpenIdConnect; @@ -41,6 +43,7 @@ public static void ConfigureAuthentication(this IServiceCollection services, Lea options.SlidingExpiration = true; options.EventsType = typeof(CookieEventHandler); options.AccessDeniedPath = "/Home/AccessDenied"; + options.SessionStore = new InMemoryTicketStore(new ConcurrentDictionary()); }) .AddOpenIdConnect(AuthenticationScheme, options => {