Skip to content

Commit 95f435c

Browse files
Merge pull request #1030 from TechnologyEnhancedLearning/Develop/Fixes/TD-3734-Concurrent-Sessions-Allowed
TD-3743: Concurrent Sessions Allowed
2 parents 6fa7544 + 354f220 commit 95f435c

File tree

2 files changed

+107
-0
lines changed

2 files changed

+107
-0
lines changed
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
namespace LearningHub.Nhs.WebUI.Helpers
2+
{
3+
using System;
4+
using System.Collections.Concurrent;
5+
using System.Linq;
6+
using System.Threading.Tasks;
7+
using Microsoft.AspNetCore.Authentication;
8+
using Microsoft.AspNetCore.Authentication.Cookies;
9+
10+
/// <summary>
11+
/// Defines the <see cref="InMemoryTicketStore" />.
12+
/// </summary>
13+
public class InMemoryTicketStore : ITicketStore
14+
{
15+
private readonly ConcurrentDictionary<string, AuthenticationTicket> cache;
16+
17+
/// <summary>
18+
/// Initializes a new instance of the <see cref="InMemoryTicketStore"/> class.
19+
/// The InMemoryTicketStore.
20+
/// </summary>
21+
/// <param name="cache">the cache.</param>
22+
public InMemoryTicketStore(ConcurrentDictionary<string, AuthenticationTicket> cache)
23+
{
24+
this.cache = cache;
25+
}
26+
27+
/// <summary>
28+
/// The StoreAsync.
29+
/// </summary>
30+
/// <param name="ticket">The ticket.</param>
31+
/// <returns>The key.</returns>
32+
public async Task<string> StoreAsync(AuthenticationTicket ticket)
33+
{
34+
var ticketUserId = ticket.Principal.Claims.Where(c => c.Type == "sub")
35+
.FirstOrDefault()
36+
.Value;
37+
var matchingAuthTicket = this.cache.Values.FirstOrDefault(
38+
t => t.Principal.Claims.FirstOrDefault(
39+
c => c.Type == "sub"
40+
&& c.Value == ticketUserId) != null);
41+
if (matchingAuthTicket != null)
42+
{
43+
var cacheKey = this.cache.Where(
44+
entry => entry.Value == matchingAuthTicket)
45+
.Select(entry => entry.Key)
46+
.FirstOrDefault();
47+
this.cache.TryRemove(
48+
cacheKey,
49+
out _);
50+
}
51+
52+
var key = Guid
53+
.NewGuid()
54+
.ToString();
55+
await this.RenewAsync(
56+
key,
57+
ticket);
58+
return key;
59+
}
60+
61+
/// <summary>
62+
/// The RenewAsync.
63+
/// </summary>
64+
/// <param name="key">The key.</param>
65+
/// <param name="ticket">The ticket.</param>
66+
/// <returns>The Task.</returns>
67+
public Task RenewAsync(
68+
string key,
69+
AuthenticationTicket ticket)
70+
{
71+
this.cache.AddOrUpdate(
72+
key,
73+
ticket,
74+
(_, _) => ticket);
75+
return Task.CompletedTask;
76+
}
77+
78+
/// <summary>
79+
/// The RetrieveAsync.
80+
/// </summary>
81+
/// <param name="key">The Key.</param>
82+
/// <returns>The Task.</returns>
83+
public Task<AuthenticationTicket> RetrieveAsync(string key)
84+
{
85+
this.cache.TryGetValue(
86+
key,
87+
out var ticket);
88+
return Task.FromResult(ticket);
89+
}
90+
91+
/// <summary>
92+
/// The RemoveAsync.
93+
/// </summary>
94+
/// <param name="key">The key.</param>
95+
/// <returns>The Task.</returns>
96+
public Task RemoveAsync(string key)
97+
{
98+
this.cache.TryRemove(
99+
key,
100+
out _);
101+
return Task.CompletedTask;
102+
}
103+
}
104+
}

LearningHub.Nhs.WebUI/Startup/AuthenticationConfiguration.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
namespace LearningHub.Nhs.WebUI.Startup
22
{
33
using System;
4+
using System.Collections.Concurrent;
45
using System.Linq;
56
using System.Threading.Tasks;
67
using IdentityModel;
78
using LearningHub.Nhs.Caching;
89
using LearningHub.Nhs.WebUI.Configuration;
910
using LearningHub.Nhs.WebUI.Handlers;
11+
using LearningHub.Nhs.WebUI.Helpers;
1012
using Microsoft.AspNetCore.Authentication;
1113
using Microsoft.AspNetCore.Authentication.Cookies;
1214
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
@@ -41,6 +43,7 @@ public static void ConfigureAuthentication(this IServiceCollection services, Lea
4143
options.SlidingExpiration = true;
4244
options.EventsType = typeof(CookieEventHandler);
4345
options.AccessDeniedPath = "/Home/AccessDenied";
46+
options.SessionStore = new InMemoryTicketStore(new ConcurrentDictionary<string, AuthenticationTicket>());
4447
})
4548
.AddOpenIdConnect(AuthenticationScheme, options =>
4649
{

0 commit comments

Comments
 (0)