Skip to content

Commit 37d9c0f

Browse files
committed
Fix Programmatic Login and AuthenticationStateProvider for Blazor Server
1 parent ad22a86 commit 37d9c0f

File tree

14 files changed

+185
-101
lines changed

14 files changed

+185
-101
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
@page "/"
22
@page "/login"
33
@using CodeBeam.UltimateAuth.Client
4+
@using CodeBeam.UltimateAuth.Client.Authentication
45
@using CodeBeam.UltimateAuth.Client.Diagnostics
56
@using CodeBeam.UltimateAuth.Core.Abstractions
67
@using CodeBeam.UltimateAuth.Core.Runtime

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

Lines changed: 0 additions & 22 deletions
This file was deleted.

samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer/Program.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
using CodeBeam.UltimateAuth.Client.Authentication;
12
using CodeBeam.UltimateAuth.Client.Extensions;
23
using CodeBeam.UltimateAuth.Core.Domain;
34
using CodeBeam.UltimateAuth.Core.Extensions;
45
using CodeBeam.UltimateAuth.Credentials.InMemory;
6+
using CodeBeam.UltimateAuth.Sample.BlazorServer.Components;
57
using CodeBeam.UltimateAuth.Security.Argon2;
68
using CodeBeam.UltimateAuth.Server.Authentication;
79
using CodeBeam.UltimateAuth.Server.Extensions;
@@ -10,7 +12,6 @@
1012
using Microsoft.AspNetCore.Components;
1113
using MudBlazor.Services;
1214
using MudExtensions.Services;
13-
using CodeBeam.UltimateAuth.Sample.BlazorServer.Components;
1415

1516
var builder = WebApplication.CreateBuilder(args);
1617

@@ -38,6 +39,12 @@
3839

3940
builder.Services.AddHttpContextAccessor();
4041

42+
builder.Services.AddScoped<IUAuthAuthenticationStateSource, ServerAuthStateSource>();
43+
//builder.Services.AddScoped<UAuthBlazorServerAuthenticationStateProvider>();
44+
45+
//builder.Services.AddScoped<AuthenticationStateProvider>(sp =>
46+
// sp.GetRequiredService<UAuthBlazorServerAuthenticationStateProvider>());
47+
4148
builder.Services.AddUltimateAuth();
4249

4350
builder.Services.AddUltimateAuthServer(o => {
@@ -57,8 +64,6 @@
5764
o.Reauth.Behavior = ReauthBehavior.RaiseEvent;
5865
});
5966

60-
61-
6267
builder.Services.AddScoped(sp =>
6368
{
6469
var navigation = sp.GetRequiredService<NavigationManager>();

samples/blazor-standalone-wasm/CodeBeam.UltimateAuth.Sample.BlazorStandaloneWasm/Program.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1+
using CodeBeam.UltimateAuth.Client.Authentication;
12
using CodeBeam.UltimateAuth.Client.Extensions;
23
using CodeBeam.UltimateAuth.Core.Extensions;
4+
using CodeBeam.UltimateAuth.Sample.BlazorStandaloneWasm;
5+
using Microsoft.AspNetCore.Components.Authorization;
36
using Microsoft.AspNetCore.Components.Web;
47
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
5-
using CodeBeam.UltimateAuth.Sample.BlazorStandaloneWasm;
68
using MudBlazor.Services;
79
using MudExtensions.Services;
8-
using Microsoft.AspNetCore.Components.Authorization;
910

1011
var builder = WebAssemblyHostBuilder.CreateDefault(args);
1112
builder.RootComponents.Add<App>("#app");
@@ -18,6 +19,10 @@
1819
{
1920
o.Endpoints.Authority = "https://localhost:6110";
2021
});
22+
23+
builder.Services.AddScoped<AuthenticationStateProvider, UAuthAuthenticationStateProvider>();
24+
builder.Services.AddScoped<IUAuthAuthenticationStateSource, ClientAuthStateSource>();
25+
2126
builder.Services.AddAuthorizationCore();
2227

2328
builder.Services.AddMudServices();
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using Microsoft.AspNetCore.Components.Authorization;
2+
3+
namespace CodeBeam.UltimateAuth.Client.Authentication
4+
{
5+
public sealed class ClientAuthStateSource : IUAuthAuthenticationStateSource
6+
{
7+
private readonly IUAuthClient _client;
8+
9+
public event Action? StateChanged;
10+
11+
public ClientAuthStateSource(IUAuthClient client)
12+
{
13+
_client = client;
14+
}
15+
16+
public async Task<AuthenticationState> GetStateAsync()
17+
{
18+
var principal = await _client.GetCurrentPrincipalAsync();
19+
return new AuthenticationState(principal);
20+
}
21+
22+
public void NotifyChanged() => StateChanged?.Invoke();
23+
}
24+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using Microsoft.AspNetCore.Components.Authorization;
2+
3+
namespace CodeBeam.UltimateAuth.Client.Authentication
4+
{
5+
public interface IUAuthAuthenticationStateSource
6+
{
7+
Task<AuthenticationState> GetStateAsync();
8+
event Action? StateChanged;
9+
}
10+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using Microsoft.AspNetCore.Components.Authorization;
2+
3+
namespace CodeBeam.UltimateAuth.Client.Authentication
4+
{
5+
public sealed class ServerAuthStateSource : IUAuthAuthenticationStateSource
6+
{
7+
private readonly AuthenticationStateProvider _provider;
8+
9+
public event Action? StateChanged;
10+
11+
public ServerAuthStateSource(AuthenticationStateProvider provider)
12+
{
13+
_provider = provider;
14+
_provider.AuthenticationStateChanged += _ => StateChanged?.Invoke();
15+
}
16+
17+
public Task<AuthenticationState> GetStateAsync()
18+
=> _provider.GetAuthenticationStateAsync();
19+
}
20+
}

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

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,14 @@ namespace CodeBeam.UltimateAuth.Client.Authentication
44
{
55
public sealed class UAuthAuthenticationStateProvider : AuthenticationStateProvider
66
{
7-
private readonly IUAuthClient _client;
7+
private readonly IUAuthAuthenticationStateSource _source;
88

9-
public UAuthAuthenticationStateProvider(IUAuthClient client)
9+
public UAuthAuthenticationStateProvider(IUAuthAuthenticationStateSource source)
1010
{
11-
_client = client;
11+
_source = source;
12+
_source.StateChanged += () => NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
1213
}
1314

14-
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
15-
{
16-
var principal = await _client.GetCurrentPrincipalAsync();
17-
return new AuthenticationState(principal);
18-
}
19-
20-
public void NotifyStateChanged()
21-
{
22-
NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
23-
}
15+
public override Task<AuthenticationState> GetAuthenticationStateAsync() => _source.GetStateAsync();
2416
}
2517
}

src/CodeBeam.UltimateAuth.Client/Extensions/UltimateAuthClientServiceCollectionExtensions.cs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -71,15 +71,17 @@ private static IServiceCollection AddUltimateAuthClientInternal(this IServiceCol
7171
// services.AddSingleton<IValidateOptions<UAuthClientOptions>, ...>();
7272

7373
services.AddSingleton<IClientProfileDetector, UAuthClientProfileDetector>();
74-
services.PostConfigure<UAuthOptions>(o =>
75-
{
76-
if (!o.AutoDetectClientProfile || o.ClientProfile != UAuthClientProfile.NotSpecified)
77-
return;
74+
services.AddSingleton<IPostConfigureOptions<UAuthOptions>, UAuthOptionsPostConfigure>();
7875

79-
using var sp = services.BuildServiceProvider();
80-
var detector = sp.GetRequiredService<IClientProfileDetector>();
81-
o.ClientProfile = detector.Detect(sp);
82-
});
76+
//services.PostConfigure<UAuthOptions>(o =>
77+
//{
78+
// if (!o.AutoDetectClientProfile || o.ClientProfile != UAuthClientProfile.NotSpecified)
79+
// return;
80+
81+
// using var sp = services.BuildServiceProvider();
82+
// var detector = sp.GetRequiredService<IClientProfileDetector>();
83+
// o.ClientProfile = detector.Detect(sp);
84+
//});
8385

8486
services.PostConfigure<UAuthClientOptions>(o =>
8587
{
@@ -88,12 +90,11 @@ private static IServiceCollection AddUltimateAuthClientInternal(this IServiceCol
8890

8991
services.AddScoped<IBrowserPostClient, BrowserPostClient>();
9092
services.AddScoped<IUAuthClient, UAuthClient>();
93+
services.AddScoped<IClientAuthState, ClientAuthState>();
9194

9295
services.AddScoped<ISessionCoordinator>(sp =>
9396
{
94-
var core = sp
95-
.GetRequiredService<IOptions<UAuthOptions>>()
96-
.Value;
97+
var core = sp.GetRequiredService<IOptions<UAuthOptions>>().Value;
9798

9899
return core.ClientProfile == UAuthClientProfile.BlazorServer
99100
? sp.GetRequiredService<BlazorServerSessionCoordinator>()
@@ -102,13 +103,13 @@ private static IServiceCollection AddUltimateAuthClientInternal(this IServiceCol
102103

103104
services.AddScoped<UAuthAuthenticationStateProvider>();
104105

105-
services.AddScoped<AuthenticationStateProvider>(sp =>
106-
sp.GetRequiredService<UAuthAuthenticationStateProvider>());
106+
// Uncomment causes blazor server to circular DI
107+
//services.AddScoped<AuthenticationStateProvider>(sp =>
108+
// sp.GetRequiredService<UAuthAuthenticationStateProvider>());
107109

108110
services.AddScoped<BlazorServerSessionCoordinator>();
109111
services.AddScoped<NoOpSessionCoordinator>();
110112
services.AddScoped<UAuthClientDiagnostics>();
111-
services.AddScoped<IClientAuthState, ClientAuthState>();
112113

113114
return services;
114115
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using CodeBeam.UltimateAuth.Core.Options;
2+
using Microsoft.Extensions.Options;
3+
4+
namespace CodeBeam.UltimateAuth.Client.Infrastructure
5+
{
6+
internal sealed class UAuthOptionsPostConfigure : IPostConfigureOptions<UAuthOptions>
7+
{
8+
private readonly IClientProfileDetector _detector;
9+
private readonly IServiceProvider _services;
10+
11+
public UAuthOptionsPostConfigure(IClientProfileDetector detector, IServiceProvider services)
12+
{
13+
_detector = detector;
14+
_services = services;
15+
}
16+
17+
public void PostConfigure(string? name, UAuthOptions options)
18+
{
19+
if (!options.AutoDetectClientProfile)
20+
return;
21+
22+
if (options.ClientProfile != UAuthClientProfile.NotSpecified)
23+
return;
24+
25+
options.ClientProfile = _detector.Detect(_services);
26+
}
27+
}
28+
}

0 commit comments

Comments
 (0)