Skip to content

Commit e8aa689

Browse files
committed
Improved UAuthStateManager
1 parent 40add40 commit e8aa689

File tree

18 files changed

+119
-76
lines changed

18 files changed

+119
-76
lines changed
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
<CascadingAuthenticationState>
1+
<UAuthApp>
22
<Router AppAssembly="typeof(Program).Assembly" NotFoundPage="typeof(Pages.NotFound)">
33
<Found Context="routeData">
44
<AuthorizeRouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)" />
55
<FocusOnNavigate RouteData="routeData" Selector="h1" />
66
</Found>
77
</Router>
8-
</CascadingAuthenticationState>
8+
</UAuthApp>

samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer/Components/Pages/Home.razor

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,34 @@
22
@attribute [Authorize]
33

44
@inject AuthenticationStateProvider AuthProvider
5-
@inject IUAuthStateManager StateManager
65
@inject IUAuthClient UAuthClient
76

8-
<MudPage FullScreen="FullScreen.Full">
7+
<MudPage Class="mud-width-full" FullScreen="FullScreen.Full" Column="1" Row="1">
98
<MudGrid>
109
<MudItem xs="12" sm="6">
1110
<MudPaper Class="pa-6">
1211

1312
<MudAvatar Size="Size.Large" Color="Color.Primary">
14-
@(_aspNetUserName?.Substring(0, 1).ToUpper())
13+
@(AuthState?.UserKey?.Value.Substring(0, 2).ToUpper())
1514
</MudAvatar>
1615

17-
<MudText Typo="Typo.h5" Class="mt-2">
18-
@_aspNetUserName
19-
</MudText>
20-
2116
<MudDivider Class="my-4" />
2217

23-
<MudText><b>ASP.NET Authenticated:</b> @_aspNetAuthenticated</MudText>
24-
<MudText><b>UAuth Authenticated:</b> @_uAuthAuthenticated</MudText>
18+
<MudText Typo="Typo.h6"><b>ASP.NET Core State</b></MudText>
19+
<MudText>IsAuthenticated: @_aspNetCoreState?.Identity?.IsAuthenticated</MudText>
20+
<MudText>User Id: @_aspNetCoreState?.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value</MudText>
21+
<MudText>User Name: @_aspNetCoreState?.Identity?.Name</MudText>
22+
<MudText>Authentication Type: @_aspNetCoreState?.Identity?.AuthenticationType</MudText>
23+
<MudText>Is Admin: @_aspNetCoreState?.IsInRole("Admin")</MudText>
2524

26-
<MudText><b>UserKey:</b> @_uAuthUserKey</MudText>
27-
<MudText><b>Client Profile:</b> @_clientProfile</MudText>
28-
<MudText><b>Tenant:</b> @_tenant</MudText>
25+
<MudDivider Class="my-4" />
2926

27+
<MudText Typo="Typo.h6"><b>UAuth State</b></MudText>
28+
<MudText>IsAuthenticated: @AuthState.IsAuthenticated</MudText>
29+
<MudText>UserKey: @AuthState.UserKey</MudText>
30+
<MudText>Tenant: @AuthState.Tenant</MudText>
31+
<MudText>Authenticated At: @AuthState.AuthenticatedAt</MudText>
32+
<MudText>Roles: @string.Join(", ", AuthState.Claims.Roles)</MudText>
3033
</MudPaper>
3134
</MudItem>
3235

@@ -65,5 +68,4 @@
6568
</MudPaper>
6669
</MudItem>
6770
</MudGrid>
68-
6971
</MudPage>

samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer/Components/Pages/Home.razor.cs

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,24 @@
1-
namespace CodeBeam.UltimateAuth.Sample.BlazorServer.Components.Pages;
1+
using CodeBeam.UltimateAuth.Client;
2+
using Microsoft.AspNetCore.Components;
3+
using Microsoft.AspNetCore.Components.Authorization;
4+
using System.Security.Claims;
5+
6+
namespace CodeBeam.UltimateAuth.Sample.BlazorServer.Components.Pages;
27

38
public partial class Home
49
{
5-
private string? _aspNetUserName;
6-
private bool _aspNetAuthenticated;
7-
private bool _uAuthAuthenticated;
8-
private string? _uAuthUserKey;
9-
private string? _clientProfile;
10-
private string? _tenant;
11-
12-
protected override async Task OnInitializedAsync()
13-
{
14-
var state = await AuthProvider.GetAuthenticationStateAsync();
15-
var user = state.User;
10+
private ClaimsPrincipal? _aspNetCoreState;
1611

17-
_aspNetAuthenticated = user.Identity?.IsAuthenticated == true;
18-
_aspNetUserName = user.Identity?.Name;
12+
[CascadingParameter]
13+
public UAuthState AuthState { get; set; } = default!;
1914

20-
var uAuth = StateManager.State;
15+
[CascadingParameter]
16+
Task<AuthenticationState> AuthenticationStateTask { get; set; } = default!;
2117

22-
_uAuthAuthenticated = uAuth?.IsAuthenticated == true;
23-
_uAuthUserKey = uAuth?.UserKey?.ToString();
24-
_tenant = uAuth?.Tenant.Value;
18+
protected override async Task OnInitializedAsync()
19+
{
20+
var state = await AuthenticationStateTask;
21+
_aspNetCoreState = state.User;
2522
}
2623

2724
private async Task Logout()
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
<UAuthAuthenticationState>
1+
<UAuthApp>
22
<Router AppAssembly="typeof(Program).Assembly" AdditionalAssemblies="new[] { typeof(UAuthClientMarker).Assembly }">
33
<Found Context="routeData">
44
<AuthorizeRouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)" />
55
<FocusOnNavigate RouteData="routeData" Selector="h1" />
66
</Found>
77
</Router>
8-
</UAuthAuthenticationState>
8+
</UAuthApp>

samples/blazor-standalone-wasm/CodeBeam.UltimateAuth.Sample.BlazorStandaloneWasm/App.razor

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<MudSnackbarProvider />
44
<MudDialogProvider />
55

6-
<UAuthAuthenticationState>
6+
<UAuthApp>
77
<Router AppAssembly="@typeof(App).Assembly">
88
<Found Context="routeData">
99
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
@@ -16,4 +16,4 @@
1616
</LayoutView>
1717
</NotFound>
1818
</Router>
19-
</UAuthAuthenticationState>
19+
</UAuthApp>

src/CodeBeam.UltimateAuth.Client/Authentication/IUAuthStateManager.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public interface IUAuthStateManager
1616
/// Ensures the authentication state is valid.
1717
/// May call server validate/refresh if needed.
1818
/// </summary>
19-
Task EnsureAsync(CancellationToken ct = default);
19+
Task EnsureAsync(bool force = false, CancellationToken ct = default);
2020

2121
/// <summary>
2222
/// Called after a successful login.

src/CodeBeam.UltimateAuth.Client/Authentication/UAuthState.cs

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using CodeBeam.UltimateAuth.Core.Contracts;
22
using CodeBeam.UltimateAuth.Core.Domain;
3+
using CodeBeam.UltimateAuth.Core.Extensions;
34
using CodeBeam.UltimateAuth.Core.MultiTenancy;
45
using System.Security.Claims;
56

@@ -45,26 +46,19 @@ private UAuthState() { }
4546

4647
internal void ApplySnapshot(AuthStateSnapshot snapshot, DateTimeOffset validatedAt)
4748
{
48-
if (string.IsNullOrWhiteSpace(snapshot.UserKey))
49-
{
50-
Clear();
51-
return;
52-
}
53-
54-
UserKey = CodeBeam.UltimateAuth.Core.Domain.UserKey.FromString(snapshot.UserKey);
55-
Tenant = snapshot.Tenant;
49+
UserKey = snapshot.Identity.UserKey;
50+
Tenant = snapshot.Identity.Tenant;
5651
Claims = snapshot.Claims;
5752

5853
IsAuthenticated = true;
5954

60-
AuthenticatedAt = snapshot.AuthenticatedAt;
55+
AuthenticatedAt = snapshot.Identity.AuthenticatedAt;
6156
LastValidatedAt = validatedAt;
6257
IsStale = false;
6358

6459
Changed?.Invoke(UAuthStateChangeReason.Authenticated);
6560
}
6661

67-
6862
internal void MarkValidated(DateTimeOffset now)
6963
{
7064
if (!IsAuthenticated)
@@ -104,15 +98,16 @@ internal void Clear()
10498
/// </summary>
10599
public ClaimsPrincipal ToClaimsPrincipal(string authenticationType = "UltimateAuth")
106100
{
107-
if (!IsAuthenticated)
101+
if (!IsAuthenticated || UserKey is null)
108102
return new ClaimsPrincipal(new ClaimsIdentity());
109103

110-
var identity = new ClaimsIdentity(
111-
Claims.AsDictionary()
112-
.Select(kv => new Claim(kv.Key, kv.Value)),
113-
authenticationType);
104+
var claims = Claims.ToClaims().ToList();
105+
claims.Add(new Claim(ClaimTypes.NameIdentifier, UserKey.Value));
106+
107+
if (!string.IsNullOrWhiteSpace(Claims.Get(ClaimTypes.Name)))
108+
claims.Add(new Claim(ClaimTypes.Name, Claims.Get(ClaimTypes.Name)!));
114109

110+
var identity = new ClaimsIdentity(claims, authenticationType, ClaimTypes.Name, ClaimTypes.Role);
115111
return new ClaimsPrincipal(identity);
116112
}
117-
118113
}

src/CodeBeam.UltimateAuth.Client/Authentication/UAuthStateManager.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ public UAuthStateManager(IUAuthClient client, IClock clock, IUAuthClientBootstra
1818
_bootstrapper = bootstrapper;
1919
}
2020

21-
public async Task EnsureAsync(CancellationToken ct = default)
21+
public async Task EnsureAsync(bool force = false, CancellationToken ct = default)
2222
{
23-
if (State.IsAuthenticated && !State.IsStale)
23+
if (!force && State.IsAuthenticated && !State.IsStale)
2424
return;
2525

2626
await _bootstrapper.EnsureStartedAsync();
@@ -51,4 +51,6 @@ public void MarkStale()
5151
{
5252
State.MarkStale();
5353
}
54+
55+
public bool NeedsValidation => !State.IsAuthenticated || State.IsStale;
5456
}

src/CodeBeam.UltimateAuth.Client/Components/UAuthAuthenticationState.razor renamed to src/CodeBeam.UltimateAuth.Client/Components/UAuthApp.razor

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
@inject IUAuthClientBootstrapper Bootstrapper
99

1010
<CascadingAuthenticationState>
11-
<CascadingValue Value="@_uauthState" IsFixed="false">
11+
<CascadingValue Value="@StateManager.State" IsFixed="false">
1212
@ChildContent
1313
</CascadingValue>
1414
</CascadingAuthenticationState>

src/CodeBeam.UltimateAuth.Client/Components/UAuthAuthenticationState.razor.cs renamed to src/CodeBeam.UltimateAuth.Client/Components/UAuthApp.razor.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@
22

33
namespace CodeBeam.UltimateAuth.Client;
44

5-
public partial class UAuthAuthenticationState
5+
public partial class UAuthApp
66
{
77
private bool _initialized;
8-
private UAuthState _uauthState = UAuthState.Anonymous();
98

109
[Parameter]
1110
public RenderFragment ChildContent { get; set; } = default!;
@@ -21,19 +20,20 @@ protected override async Task OnAfterRenderAsync(bool firstRender)
2120
_initialized = true;
2221
//await Bootstrapper.EnsureStartedAsync();
2322
await StateManager.EnsureAsync();
24-
_uauthState = StateManager.State;
2523

2624
StateManager.State.Changed += OnStateChanged;
2725
}
2826

29-
private void OnStateChanged(UAuthStateChangeReason _)
27+
private void OnStateChanged(UAuthStateChangeReason reason)
3028
{
31-
//StateManager.EnsureAsync();
32-
if (_ == UAuthStateChangeReason.MarkedStale)
29+
if (reason == UAuthStateChangeReason.MarkedStale)
3330
{
34-
StateManager.EnsureAsync();
31+
_ = InvokeAsync(async () =>
32+
{
33+
await StateManager.EnsureAsync();
34+
});
3535
}
36-
_uauthState = StateManager.State;
36+
3737
InvokeAsync(StateHasChanged);
3838
}
3939

0 commit comments

Comments
 (0)