Skip to content

Commit 05db576

Browse files
committed
Added Policy Project
1 parent 16856a3 commit 05db576

File tree

53 files changed

+747
-167
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+747
-167
lines changed

UltimateAuth.slnx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
<Project Path="src/credentials/CodeBeam.UltimateAuth.Credentials.InMemory/CodeBeam.UltimateAuth.Credentials.InMemory.csproj" Id="62ee7b1d-46ce-4f2e-985d-1e794f891b8b" />
2525
<Project Path="src/credentials/CodeBeam.UltimateAuth.Credentials.Reference/CodeBeam.UltimateAuth.Credentials.Reference.csproj" Id="ca03a140-f3dc-4a21-9b7d-895a3b10808b" />
2626
<Project Path="src/credentials/CodeBeam.UltimateAuth.Credentials/CodeBeam.UltimateAuth.Credentials.csproj" Id="2281c3b5-1d60-4542-a673-553f96eed25b" />
27+
<Project Path="src/policies/CodeBeam.UltimateAuth.Policies/CodeBeam.UltimateAuth.Policies.csproj" Id="b37c337f-2446-4f54-8684-b72fa83ac444" />
2728
<Project Path="src/security/CodeBeam.UltimateAuth.Security.Argon2/CodeBeam.UltimateAuth.Security.Argon2.csproj" Id="6abfb7a6-ea36-42db-a843-38054dd40fd8" />
2829
<Project Path="src/sessions/CodeBeam.UltimateAuth.Sessions.EntityFrameworkCore/CodeBeam.UltimateAuth.Sessions.EntityFrameworkCore.csproj" Id="5b9a090d-1689-4a81-9dfa-3ba69f0bda38" />
2930
<Project Path="src/sessions/CodeBeam.UltimateAuth.Sessions.InMemory/CodeBeam.UltimateAuth.Sessions.InMemory.csproj" Id="fc9bfef0-8a89-4639-81ee-3f84f6e33816" />

src/CodeBeam.UltimateAuth.Server/CodeBeam.UltimateAuth.Server.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
<ProjectReference Include="..\CodeBeam.UltimateAuth.Core\CodeBeam.UltimateAuth.Core.csproj" />
2424
<ProjectReference Include="..\credentials\CodeBeam.UltimateAuth.Credentials.Contracts\CodeBeam.UltimateAuth.Credentials.Contracts.csproj" />
2525
<ProjectReference Include="..\credentials\CodeBeam.UltimateAuth.Credentials\CodeBeam.UltimateAuth.Credentials.csproj" />
26+
<ProjectReference Include="..\policies\CodeBeam.UltimateAuth.Policies\CodeBeam.UltimateAuth.Policies.csproj" />
2627
<ProjectReference Include="..\users\CodeBeam.UltimateAuth.Users.Contracts\CodeBeam.UltimateAuth.Users.Contracts.csproj" />
2728
<ProjectReference Include="..\users\CodeBeam.UltimateAuth.Users\CodeBeam.UltimateAuth.Users.csproj" />
2829
</ItemGroup>

src/CodeBeam.UltimateAuth.Server/Defaults/UAuthActions.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,15 @@ public static class Credentials
3535
public const string Delete = "credentials.delete";
3636
}
3737

38+
public static class Authorization
39+
{
40+
public static class Roles
41+
{
42+
public const string Read = "authorization.roles.read";
43+
public const string Assign = "authorization.roles.assign";
44+
public const string Remove = "authorization.roles.remove";
45+
}
46+
}
47+
3848
}
3949
}

src/CodeBeam.UltimateAuth.Server/Endpoints/UAuthEndpointRegistrar.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,9 @@ public void MapEndpoints(RouteGroupBuilder rootGroup, UAuthServerOptions options
173173
authz.MapPost("/check", async ([FromServices] IAuthorizationEndpointHandler h, HttpContext ctx)
174174
=> await h.CheckAsync(ctx)).WithMetadata(new AuthFlowMetadata(AuthFlowType.AuthorizationManagement));
175175

176+
authz.MapGet("/users/{userKey}/roles", async ([FromServices] IAuthorizationEndpointHandler h, UserKey userKey, HttpContext ctx)
177+
=> await h.GetRolesAsync(userKey, ctx)).WithMetadata(new AuthFlowMetadata(AuthFlowType.AuthorizationManagement));
178+
176179
authz.MapPost("/users/{userKey}/roles", async ([FromServices] IAuthorizationEndpointHandler h, UserKey userKey, HttpContext ctx)
177180
=> await h.AssignRoleAsync(userKey, ctx)).WithMetadata(new AuthFlowMetadata(AuthFlowType.AuthorizationManagement));
178181

src/CodeBeam.UltimateAuth.Server/Extensions/UAuthServerServiceCollectionExtensions.cs

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@
77
using CodeBeam.UltimateAuth.Core.MultiTenancy;
88
using CodeBeam.UltimateAuth.Core.Options;
99
using CodeBeam.UltimateAuth.Credentials;
10+
using CodeBeam.UltimateAuth.Policies.Abstractions;
11+
using CodeBeam.UltimateAuth.Policies.Defaults;
12+
using CodeBeam.UltimateAuth.Policies.Registry;
1013
using CodeBeam.UltimateAuth.Server.Abstactions;
1114
using CodeBeam.UltimateAuth.Server.Abstractions;
1215
using CodeBeam.UltimateAuth.Server.Auth;
13-
using CodeBeam.UltimateAuth.Server.Auth.Context;
1416
using CodeBeam.UltimateAuth.Server.Cookies;
1517
using CodeBeam.UltimateAuth.Server.Endpoints;
1618
using CodeBeam.UltimateAuth.Server.Infrastructure;
@@ -23,7 +25,6 @@
2325
using CodeBeam.UltimateAuth.Server.Options;
2426
using CodeBeam.UltimateAuth.Server.Services;
2527
using CodeBeam.UltimateAuth.Server.Stores;
26-
using CodeBeam.UltimateAuth.Users;
2728
using Microsoft.Extensions.Configuration;
2829
using Microsoft.Extensions.DependencyInjection;
2930
using Microsoft.Extensions.DependencyInjection.Extensions;
@@ -39,6 +40,7 @@ public static IServiceCollection AddUltimateAuthServer(this IServiceCollection s
3940
services.AddUltimateAuth();
4041
AddUsersInternal(services);
4142
AddCredentialsInternal(services);
43+
AddUltimateAuthPolicies(services);
4244
return services.AddUltimateAuthServerInternal();
4345
}
4446

@@ -47,6 +49,7 @@ public static IServiceCollection AddUltimateAuthServer(this IServiceCollection s
4749
services.AddUltimateAuth(configuration);
4850
AddUsersInternal(services);
4951
AddCredentialsInternal(services);
52+
AddUltimateAuthPolicies(services);
5053
services.Configure<UAuthServerOptions>(configuration.GetSection("UltimateAuth:Server"));
5154

5255
return services.AddUltimateAuthServerInternal();
@@ -57,6 +60,7 @@ public static IServiceCollection AddUltimateAuthServer(this IServiceCollection s
5760
services.AddUltimateAuth();
5861
AddUsersInternal(services);
5962
AddCredentialsInternal(services);
63+
AddUltimateAuthPolicies(services);
6064
services.Configure(configure);
6165

6266
return services.AddUltimateAuthServerInternal();
@@ -248,14 +252,40 @@ private static IServiceCollection AddUltimateAuthServerInternal(this IServiceCol
248252
//services.TryAddScoped<ITokenEndpointHandler, TokenEndpointHandler>();
249253
//services.TryAddScoped<IUserInfoEndpointHandler, UserInfoEndpointHandler>();
250254

251-
services.ConfigureHttpJsonOptions(o =>
255+
return services;
256+
}
257+
258+
internal static IServiceCollection AddUltimateAuthPolicies(this IServiceCollection services, Action<AccessPolicyRegistry>? configure = null)
259+
{
260+
if (services.Any(d => d.ServiceType == typeof(AccessPolicyRegistry)))
261+
throw new InvalidOperationException("UltimateAuth policies already registered.");
262+
263+
var registry = new AccessPolicyRegistry();
264+
265+
DefaultPolicySet.Register(registry);
266+
configure?.Invoke(registry);
267+
services.AddSingleton(registry);
268+
services.AddSingleton<IAccessPolicyProvider>(sp =>
269+
{
270+
var compiled = registry.Build();
271+
return new DefaultAccessPolicyProvider(compiled, sp);
272+
});
273+
274+
services.TryAddScoped<IAccessAuthority>(sp =>
252275
{
253-
o.SerializerOptions.Converters.Add(new UserKeyJsonConverter());
276+
var invariants = sp.GetServices<IAccessInvariant>();
277+
var globalPolicies = sp.GetServices<IAccessPolicy>();
278+
279+
return new DefaultAccessAuthority(invariants, globalPolicies);
254280
});
255281

282+
services.TryAddScoped<IAccessOrchestrator, UAuthAccessOrchestrator>();
283+
284+
256285
return services;
257286
}
258287

288+
259289
// =========================
260290
// USERS (FRAMEWORK-REQUIRED)
261291
// =========================
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using CodeBeam.UltimateAuth.Core.Abstractions;
2+
using CodeBeam.UltimateAuth.Core.Contracts;
3+
using CodeBeam.UltimateAuth.Policies.Abstractions;
4+
using CodeBeam.UltimateAuth.Policies.Defaults;
5+
6+
namespace CodeBeam.UltimateAuth.Server.Infrastructure;
7+
8+
internal sealed class DefaultAccessPolicyProvider : IAccessPolicyProvider
9+
{
10+
private readonly CompiledAccessPolicySet _set;
11+
private readonly IServiceProvider _services;
12+
13+
public DefaultAccessPolicyProvider(CompiledAccessPolicySet set, IServiceProvider services)
14+
{
15+
_set = set;
16+
_services = services;
17+
}
18+
19+
public IReadOnlyCollection<IAccessPolicy> GetPolicies(AccessContext context) => _set.Resolve(context, _services);
20+
21+
}

src/CodeBeam.UltimateAuth.Server/Infrastructure/Orchestrator/IAccessCommand.cs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,13 @@
1-
using CodeBeam.UltimateAuth.Core.Abstractions;
2-
using CodeBeam.UltimateAuth.Core.Contracts;
3-
4-
namespace CodeBeam.UltimateAuth.Server.Infrastructure
1+
namespace CodeBeam.UltimateAuth.Server.Infrastructure
52
{
63
public interface IAccessCommand
74
{
8-
IEnumerable<IAccessPolicy> GetPolicies(AccessContext context);
95
Task ExecuteAsync(CancellationToken ct = default);
106
}
117

128
// For get commands
139
public interface IAccessCommand<TResult>
1410
{
15-
IEnumerable<IAccessPolicy> GetPolicies(AccessContext context);
1611
Task<TResult> ExecuteAsync(CancellationToken ct = default);
1712
}
1813

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,42 @@
11
using CodeBeam.UltimateAuth.Core.Abstractions;
22
using CodeBeam.UltimateAuth.Core.Contracts;
33
using CodeBeam.UltimateAuth.Core.Errors;
4+
using CodeBeam.UltimateAuth.Policies.Abstractions;
45

56
namespace CodeBeam.UltimateAuth.Server.Infrastructure
67
{
78
public sealed class UAuthAccessOrchestrator : IAccessOrchestrator
89
{
910
private readonly IAccessAuthority _authority;
10-
private bool _executed;
11+
private readonly IAccessPolicyProvider _policyProvider;
1112

12-
public UAuthAccessOrchestrator(IAccessAuthority authority)
13+
public UAuthAccessOrchestrator(IAccessAuthority authority, IAccessPolicyProvider policyProvider)
1314
{
1415
_authority = authority;
16+
_policyProvider = policyProvider;
1517
}
1618

1719
public async Task ExecuteAsync(AccessContext context, IAccessCommand command, CancellationToken ct = default)
1820
{
19-
if (_executed)
20-
throw new InvalidOperationException("Access orchestrator can only be executed once.");
21+
ct.ThrowIfCancellationRequested();
2122

22-
_executed = true;
23-
24-
var policies = command.GetPolicies(context) ?? Array.Empty<IAccessPolicy>();
23+
var policies = _policyProvider.GetPolicies(context);
2524
var decision = _authority.Decide(context, policies);
2625

2726
if (!decision.IsAllowed)
2827
throw new UAuthAuthorizationException(decision.DenyReason);
2928

3029
if (decision.RequiresReauthentication)
31-
throw new InvalidOperationException("Requires reuthenticate.");
30+
throw new InvalidOperationException("Requires reauthentication.");
3231

3332
await command.ExecuteAsync(ct);
3433
}
3534

3635
public async Task<TResult> ExecuteAsync<TResult>(AccessContext context, IAccessCommand<TResult> command, CancellationToken ct = default)
3736
{
38-
if (_executed)
39-
throw new InvalidOperationException("Access orchestrator can only be executed once.");
37+
ct.ThrowIfCancellationRequested();
4038

41-
_executed = true;
42-
43-
var policies = command.GetPolicies(context) ?? Array.Empty<IAccessPolicy>();
39+
var policies = _policyProvider.GetPolicies(context);
4440
var decision = _authority.Decide(context, policies);
4541

4642
if (!decision.IsAllowed)
@@ -51,6 +47,5 @@ public async Task<TResult> ExecuteAsync<TResult>(AccessContext context, IAccessC
5147

5248
return await command.ExecuteAsync(ct);
5349
}
54-
5550
}
5651
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using CodeBeam.UltimateAuth.Core.Abstractions;
2+
using CodeBeam.UltimateAuth.Core.Contracts;
3+
using CodeBeam.UltimateAuth.Server.Infrastructure;
4+
5+
namespace CodeBeam.UltimateAuth.Authorization.Reference
6+
{
7+
internal sealed class AssignUserRoleCommand : IAccessCommand
8+
{
9+
private readonly Func<CancellationToken, Task> _execute;
10+
private readonly IEnumerable<IAccessPolicy> _policies;
11+
12+
public AssignUserRoleCommand(IEnumerable<IAccessPolicy> policies, Func<CancellationToken, Task> execute)
13+
{
14+
_policies = policies;
15+
_execute = execute;
16+
}
17+
18+
public IEnumerable<IAccessPolicy> GetPolicies(AccessContext context) => _policies;
19+
20+
public Task ExecuteAsync(CancellationToken ct = default) => _execute(ct);
21+
}
22+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using CodeBeam.UltimateAuth.Core.Abstractions;
2+
using CodeBeam.UltimateAuth.Core.Contracts;
3+
using CodeBeam.UltimateAuth.Server.Infrastructure;
4+
5+
namespace CodeBeam.UltimateAuth.Authorization.Reference
6+
{
7+
internal sealed class GetUserRolesCommand : IAccessCommand<IReadOnlyCollection<string>>
8+
{
9+
private readonly IEnumerable<IAccessPolicy> _policies;
10+
private readonly Func<CancellationToken, Task<IReadOnlyCollection<string>>> _execute;
11+
12+
public GetUserRolesCommand(IEnumerable<IAccessPolicy> policies, Func<CancellationToken, Task<IReadOnlyCollection<string>>> execute)
13+
{
14+
_policies = policies;
15+
_execute = execute;
16+
}
17+
18+
public IEnumerable<IAccessPolicy> GetPolicies(AccessContext context) => _policies;
19+
20+
public Task<IReadOnlyCollection<string>> ExecuteAsync(CancellationToken ct = default) => _execute(ct);
21+
}
22+
}

0 commit comments

Comments
 (0)