4
4
using System . Security . Claims ;
5
5
using Duende . AccessTokenManagement . OpenIdConnect ;
6
6
using Microsoft . AspNetCore . Authentication ;
7
+ using Microsoft . AspNetCore . Components . Authorization ;
7
8
using Microsoft . AspNetCore . DataProtection ;
8
9
using Microsoft . Extensions . Logging ;
9
10
@@ -16,22 +17,33 @@ public class ServerSideTokenStore(
16
17
IStoreTokensInAuthenticationProperties tokensInAuthProperties ,
17
18
IUserSessionStore sessionStore ,
18
19
IDataProtectionProvider dataProtectionProvider ,
19
- ILogger < ServerSideTokenStore > logger ) : IUserTokenStore
20
+ ILogger < ServerSideTokenStore > logger ,
21
+ AuthenticationStateProvider authenticationStateProvider ) : IUserTokenStore
20
22
{
21
23
private readonly IDataProtector protector =
22
24
dataProtectionProvider . CreateProtector ( ServerSideTicketStore . DataProtectorPurpose ) ;
23
25
26
+ private readonly IHostEnvironmentAuthenticationStateProvider _authenticationStateProvider = authenticationStateProvider as IHostEnvironmentAuthenticationStateProvider
27
+ ?? throw new ArgumentException ( "AuthenticationStateProvider must implement IHostEnvironmentAuthenticationStateProvider" ) ;
28
+
24
29
public async Task < UserToken > GetTokenAsync ( ClaimsPrincipal user , UserTokenRequestParameters ? parameters = null )
25
30
{
26
31
logger . LogDebug ( "Retrieving token for user {user}" , user . Identity ? . Name ) ;
27
32
var session = await GetSession ( user ) ;
33
+ if ( session == null )
34
+ {
35
+ var anonymous = new ClaimsPrincipal ( new ClaimsIdentity ( ) ) ;
36
+ var loggedOutTask = Task . FromResult ( new AuthenticationState ( user : anonymous ) ) ;
37
+ _authenticationStateProvider . SetAuthenticationState ( loggedOutTask ) ;
38
+ return new UserToken ( ) ;
39
+ }
28
40
var ticket = session . Deserialize ( protector , logger ) ??
29
41
throw new InvalidOperationException ( "Failed to deserialize authentication ticket from session" ) ;
30
42
31
43
return tokensInAuthProperties . GetUserToken ( ticket . Properties , parameters ) ;
32
44
}
33
45
34
- private async Task < UserSession > GetSession ( ClaimsPrincipal user )
46
+ private async Task < UserSession ? > GetSession ( ClaimsPrincipal user )
35
47
{
36
48
var sub = user . FindFirst ( "sub" ) ? . Value ?? throw new InvalidOperationException ( "no sub claim" ) ;
37
49
var sid = user . FindFirst ( "sid" ) ? . Value ?? throw new InvalidOperationException ( "no sid claim" ) ;
@@ -44,7 +56,10 @@ private async Task<UserSession> GetSession(ClaimsPrincipal user)
44
56
SessionId = sid
45
57
} ) ;
46
58
47
- if ( sessions . Count == 0 ) throw new InvalidOperationException ( "No ticket found" ) ;
59
+ if ( sessions . Count == 0 )
60
+ {
61
+ return null ;
62
+ }
48
63
if ( sessions . Count > 1 ) throw new InvalidOperationException ( "Multiple tickets found" ) ;
49
64
50
65
return sessions . First ( ) ;
@@ -67,6 +82,11 @@ public async Task ClearTokenAsync(ClaimsPrincipal user, UserTokenRequestParamete
67
82
protected async Task UpdateTicket ( ClaimsPrincipal user , Action < AuthenticationTicket > updateAction )
68
83
{
69
84
var session = await GetSession ( user ) ;
85
+ if ( session == null )
86
+ {
87
+ logger . LogDebug ( "Failed to find a session to update, bailing out" ) ;
88
+ return ;
89
+ }
70
90
var ticket = session . Deserialize ( protector , logger ) ??
71
91
throw new InvalidOperationException ( "Failed to deserialize authentication ticket from session" ) ;
72
92
0 commit comments