Skip to content

Commit 9265d57

Browse files
committed
Completed Core Options & Improved AuthFlowContext and AccessContext Creation Security
1 parent 9a6808e commit 9265d57

30 files changed

+211
-145
lines changed

src/CodeBeam.UltimateAuth.Client/Components/UALoginForm.razor

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
@using CodeBeam.UltimateAuth.Core.Options
88
@using Microsoft.Extensions.Options
99
@inject IJSRuntime JS
10-
@inject IOptions<UAuthOptions> CoreOptions
1110
@inject IOptions<UAuthClientOptions> Options
1211
@inject NavigationManager Navigation
1312

src/CodeBeam.UltimateAuth.Client/Components/UALoginForm.razor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ public async Task SubmitAsync()
115115
await JS.InvokeVoidAsync("uauth.submitForm", _form);
116116
}
117117

118-
private string ClientProfileValue => CoreOptions.Value.ClientProfile.ToString();
118+
private string ClientProfileValue => Options.Value.ClientProfile.ToString();
119119

120120
private string EffectiveEndpoint => LoginType == UAuthLoginType.Pkce
121121
? Options.Value.Endpoints.PkceComplete

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ private static IServiceCollection AddUltimateAuthClientInternal(this IServiceCol
7979
// services.AddSingleton<IValidateOptions<UAuthClientOptions>, ...>();
8080

8181
services.AddSingleton<IClientProfileDetector, UAuthClientProfileDetector>();
82-
services.AddSingleton<IPostConfigureOptions<UAuthOptions>, UAuthOptionsPostConfigure>();
82+
services.AddSingleton<IPostConfigureOptions<UAuthClientOptions>, UAuthClientOptionsPostConfigure>();
8383
services.TryAddSingleton<IClock, ClientClock>();
8484

8585
//services.PostConfigure<UAuthOptions>(o =>
@@ -107,9 +107,9 @@ private static IServiceCollection AddUltimateAuthClientInternal(this IServiceCol
107107

108108
services.AddScoped<ISessionCoordinator>(sp =>
109109
{
110-
var core = sp.GetRequiredService<IOptions<UAuthOptions>>().Value;
110+
var options = sp.GetRequiredService<IOptions<UAuthClientOptions>>().Value;
111111

112-
return core.ClientProfile == UAuthClientProfile.BlazorServer
112+
return options.ClientProfile == UAuthClientProfile.BlazorServer
113113
? sp.GetRequiredService<BlazorServerSessionCoordinator>()
114114
: sp.GetRequiredService<NoOpSessionCoordinator>();
115115
});

src/CodeBeam.UltimateAuth.Client/Infrastructure/UAuthRequestClient.cs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using CodeBeam.UltimateAuth.Client.Abstractions;
22
using CodeBeam.UltimateAuth.Client.Contracts;
3+
using CodeBeam.UltimateAuth.Client.Options;
34
using CodeBeam.UltimateAuth.Core.Options;
45
using Microsoft.Extensions.Options;
56
using Microsoft.JSInterop;
@@ -10,12 +11,12 @@ namespace CodeBeam.UltimateAuth.Client.Infrastructure;
1011
internal sealed class UAuthRequestClient : IUAuthRequestClient
1112
{
1213
private readonly IJSRuntime _js;
13-
private UAuthOptions _coreOptions;
14+
private UAuthClientOptions _options;
1415

15-
public UAuthRequestClient(IJSRuntime js, IOptions<UAuthOptions> coreOptions)
16+
public UAuthRequestClient(IJSRuntime js, IOptions<UAuthClientOptions> options)
1617
{
1718
_js = js;
18-
_coreOptions = coreOptions.Value;
19+
_options = options.Value;
1920
}
2021

2122
public Task NavigateAsync(string endpoint, IDictionary<string, string>? form = null, CancellationToken ct = default)
@@ -27,7 +28,7 @@ public Task NavigateAsync(string endpoint, IDictionary<string, string>? form = n
2728
url = endpoint,
2829
mode = "navigate",
2930
data = form,
30-
clientProfile = _coreOptions.ClientProfile.ToString()
31+
clientProfile = _options.ClientProfile.ToString()
3132
}).AsTask();
3233
}
3334

@@ -41,7 +42,7 @@ public async Task<UAuthTransportResult> SendFormAsync(string endpoint, IDictiona
4142
mode = "fetch",
4243
expectJson = false,
4344
data = form,
44-
clientProfile = _coreOptions.ClientProfile.ToString()
45+
clientProfile = _options.ClientProfile.ToString()
4546
});
4647

4748
return result;
@@ -59,7 +60,7 @@ public async Task<UAuthTransportResult> SendFormForJsonAsync(string endpoint, ID
5960
mode = "fetch",
6061
expectJson = true,
6162
data = postData,
62-
clientProfile = _coreOptions.ClientProfile.ToString()
63+
clientProfile = _options.ClientProfile.ToString()
6364
});
6465
}
6566

@@ -71,7 +72,7 @@ public async Task<UAuthTransportResult> SendJsonAsync(string endpoint, object? p
7172
{
7273
url = endpoint,
7374
payload = payload,
74-
clientProfile = _coreOptions.ClientProfile.ToString()
75+
clientProfile = _options.ClientProfile.ToString()
7576
});
7677
}
7778

src/CodeBeam.UltimateAuth.Client/Options/UAuthClientOptions.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
using CodeBeam.UltimateAuth.Core.Domain;
2+
using CodeBeam.UltimateAuth.Core.Options;
23

34
namespace CodeBeam.UltimateAuth.Client.Options;
45

56
public sealed class UAuthClientOptions
67
{
8+
public UAuthClientProfile ClientProfile { get; set; } = UAuthClientProfile.NotSpecified;
9+
public bool AutoDetectClientProfile { get; set; } = true;
10+
711
public AuthEndpointOptions Endpoints { get; set; } = new();
812
public LoginFlowOptions Login { get; set; } = new();
913

src/CodeBeam.UltimateAuth.Client/Options/UAuthOptionsPostConfigure.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
1-
using CodeBeam.UltimateAuth.Core.Options;
1+
using CodeBeam.UltimateAuth.Client.Options;
2+
using CodeBeam.UltimateAuth.Core.Options;
23
using Microsoft.Extensions.Options;
34

45
namespace CodeBeam.UltimateAuth.Client.Infrastructure;
56

6-
internal sealed class UAuthOptionsPostConfigure : IPostConfigureOptions<UAuthOptions>
7+
internal sealed class UAuthClientOptionsPostConfigure : IPostConfigureOptions<UAuthClientOptions>
78
{
89
private readonly IClientProfileDetector _detector;
910
private readonly IServiceProvider _services;
1011

11-
public UAuthOptionsPostConfigure(IClientProfileDetector detector, IServiceProvider services)
12+
public UAuthClientOptionsPostConfigure(IClientProfileDetector detector, IServiceProvider services)
1213
{
1314
_detector = detector;
1415
_services = services;
1516
}
1617

17-
public void PostConfigure(string? name, UAuthOptions options)
18+
public void PostConfigure(string? name, UAuthClientOptions options)
1819
{
1920
if (!options.AutoDetectClientProfile)
2021
return;

src/CodeBeam.UltimateAuth.Client/Services/UAuthFlowClient.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,17 @@ internal class UAuthFlowClient : IFlowClient
1919
{
2020
private readonly IUAuthRequestClient _post;
2121
private readonly UAuthClientOptions _options;
22-
private readonly UAuthOptions _coreOptions;
2322
private readonly UAuthClientDiagnostics _diagnostics;
2423
private readonly NavigationManager _nav;
2524

2625
public UAuthFlowClient(
2726
IUAuthRequestClient post,
2827
IOptions<UAuthClientOptions> options,
29-
IOptions<UAuthOptions> coreOptions,
3028
UAuthClientDiagnostics diagnostics,
3129
NavigationManager nav)
3230
{
3331
_post = post;
3432
_options = options.Value;
35-
_coreOptions = coreOptions.Value;
3633
_diagnostics = diagnostics;
3734
_nav = nav;
3835
}
@@ -188,7 +185,7 @@ private Task NavigateToHubLoginAsync(string authorizationCode, string codeVerifi
188185
["authorization_code"] = authorizationCode,
189186
["code_verifier"] = codeVerifier,
190187
["return_url"] = returnUrl,
191-
["client_profile"] = _coreOptions.ClientProfile.ToString()
188+
["client_profile"] = _options.ClientProfile.ToString()
192189
};
193190

194191
return _post.NavigateAsync(hubLoginUrl, data);

src/CodeBeam.UltimateAuth.Core/Contracts/Authority/AccessContext.cs

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,47 @@ public sealed class AccessContext
1414

1515
// Target
1616
public string? Resource { get; init; }
17-
public string? ResourceId { get; init; }
17+
public UserKey? TargetUserKey { get; init; }
1818
public TenantKey ResourceTenant { get; init; }
1919

2020
public string Action { get; init; } = default!;
2121
public IReadOnlyDictionary<string, object> Attributes { get; init; } = EmptyAttributes.Instance;
2222

2323
public bool IsCrossTenant => !string.Equals(ActorTenant, ResourceTenant, StringComparison.Ordinal);
24-
public bool IsSelfAction => ActorUserKey != null && ResourceId != null && string.Equals(ActorUserKey.Value, ResourceId, StringComparison.Ordinal);
24+
public bool IsSelfAction => ActorUserKey != null && TargetUserKey != null && string.Equals(ActorUserKey.Value, TargetUserKey.Value, StringComparison.Ordinal);
2525
public bool HasActor => ActorUserKey != null;
26-
public bool HasTarget => ResourceId != null;
26+
public bool HasTarget => TargetUserKey != null;
2727

2828
public UserKey GetTargetUserKey()
2929
{
30-
if (ResourceId is null)
31-
throw new InvalidOperationException("Target user is not specified.");
30+
if (TargetUserKey is not UserKey targetUserKey)
31+
throw new InvalidOperationException("Target user is not found.");
3232

33-
return UserKey.Parse(ResourceId, null);
33+
return targetUserKey;
34+
}
35+
36+
internal AccessContext(
37+
UserKey? actorUserKey,
38+
TenantKey actorTenant,
39+
bool isAuthenticated,
40+
bool isSystemActor,
41+
string resource,
42+
UserKey? targetUserKey,
43+
TenantKey resourceTenant,
44+
string action,
45+
IReadOnlyDictionary<string, object> attributes)
46+
{
47+
ActorUserKey = actorUserKey;
48+
ActorTenant = actorTenant;
49+
IsAuthenticated = isAuthenticated;
50+
IsSystemActor = isSystemActor;
51+
52+
Resource = resource;
53+
TargetUserKey = targetUserKey;
54+
ResourceTenant = resourceTenant;
55+
56+
Action = action;
57+
Attributes = attributes;
3458
}
3559
}
3660

src/CodeBeam.UltimateAuth.Core/Infrastructure/UserKeyJsonConverter.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
namespace CodeBeam.UltimateAuth.Core.Infrastructure;
66

7+
// NOTE:
8+
// UserKey is the canonical domain identity type.
9+
// JSON serialization/deserialization is intentionally direct and does not use IUserIdConverterResolver.
710
public sealed class UserKeyJsonConverter : JsonConverter<UserKey>
811
{
912
public override UserKey Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)

src/CodeBeam.UltimateAuth.Core/Options/UAuthOptions.cs

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
using CodeBeam.UltimateAuth.Core.Abstractions;
2-
using CodeBeam.UltimateAuth.Core.Events;
1+
using CodeBeam.UltimateAuth.Core.Events;
32

43
namespace CodeBeam.UltimateAuth.Core.Options;
54

@@ -48,13 +47,4 @@ public sealed class UAuthOptions
4847
/// validated, and optionally enforced.
4948
/// </summary>
5049
public UAuthMultiTenantOptions MultiTenant { get; set; } = new();
51-
52-
/// <summary>
53-
/// Provides converters used to normalize and serialize TUserId
54-
/// across the system (sessions, stores, tokens, logging).
55-
/// </summary>
56-
public IUserIdConverterResolver? UserIdConverters { get; set; }
57-
58-
public UAuthClientProfile ClientProfile { get; set; } = UAuthClientProfile.NotSpecified;
59-
public bool AutoDetectClientProfile { get; set; } = true;
6050
}

0 commit comments

Comments
 (0)