|
1 | | -using CodeBeam.UltimateAuth.Core; |
| 1 | +using CodeBeam.UltimateAuth.Authorization.Contracts; |
| 2 | +using CodeBeam.UltimateAuth.Core; |
2 | 3 | using CodeBeam.UltimateAuth.Core.Contracts; |
| 4 | +using CodeBeam.UltimateAuth.Core.Defaults; |
| 5 | +using CodeBeam.UltimateAuth.Core.Runtime; |
| 6 | +using CodeBeam.UltimateAuth.Server.Auth; |
3 | 7 | using CodeBeam.UltimateAuth.Server.Extensions; |
| 8 | +using CodeBeam.UltimateAuth.Server.Runtime; |
4 | 9 | using Microsoft.AspNetCore.Http; |
5 | 10 | using Microsoft.Extensions.DependencyInjection; |
| 11 | +using System.Collections.ObjectModel; |
| 12 | +using System.Text.Json; |
6 | 13 |
|
7 | 14 | namespace CodeBeam.UltimateAuth.Server.Authorization; |
8 | 15 |
|
9 | 16 | internal static class ResourceAccessContextBuilder |
10 | 17 | { |
11 | | - public static AccessContext Create(HttpContext http, string action) |
| 18 | + public static async Task<AccessContext> CreateAsync(HttpContext http, string action, CancellationToken ct = default) |
12 | 19 | { |
13 | 20 | var user = http.RequestServices.GetRequiredService<ICurrentUser>(); |
14 | 21 |
|
| 22 | + var tenant = http.GetTenant(); |
| 23 | + |
| 24 | + IReadOnlyList<AccessActorRole> actorRoles = []; |
| 25 | + IReadOnlyDictionary<string, object> attributes = EmptyAttributes.Instance; |
| 26 | + |
| 27 | + if (user.IsAuthenticated) |
| 28 | + { |
| 29 | + RoleId[] roleIds; |
| 30 | + |
| 31 | + var runtime = http.RequestServices.GetRequiredService<IUAuthRuntimeMarker>(); |
| 32 | + |
| 33 | + if (runtime is ResourceRuntimeMarker) |
| 34 | + { |
| 35 | + // Remote session validation has already produced |
| 36 | + // the authenticated principal. |
| 37 | + var identity = http.User.Identities.SingleOrDefault(x => x.IsAuthenticated && x.AuthenticationType == UAuthConstants.SchemeDefaults.GlobalScheme); |
| 38 | + |
| 39 | + if (identity is null) |
| 40 | + throw new InvalidOperationException("Trusted UltimateAuth identity is missing."); |
| 41 | + |
| 42 | + var roles = new List<AccessActorRole>(); |
| 43 | + var ids = new List<RoleId>(); |
| 44 | + |
| 45 | + foreach (var claim in identity.FindAll(UAuthConstants.Claims.ActorRole)) |
| 46 | + { |
| 47 | + AccessActorRole? role; |
| 48 | + |
| 49 | + try |
| 50 | + { |
| 51 | + role = JsonSerializer.Deserialize<AccessActorRole>(claim.Value); |
| 52 | + } |
| 53 | + catch (JsonException) |
| 54 | + { |
| 55 | + throw new InvalidOperationException("Invalid actor role claim."); |
| 56 | + } |
| 57 | + |
| 58 | + if (role is null || |
| 59 | + string.IsNullOrWhiteSpace(role.Name) || |
| 60 | + !RoleId.TryParse(role.Id, null, out var roleId)) |
| 61 | + { |
| 62 | + throw new InvalidOperationException("Invalid actor role claim."); |
| 63 | + } |
| 64 | + |
| 65 | + roles.Add(role); |
| 66 | + ids.Add(roleId); |
| 67 | + } |
| 68 | + |
| 69 | + actorRoles = roles; |
| 70 | + roleIds = ids.ToArray(); |
| 71 | + } |
| 72 | + else |
| 73 | + { |
| 74 | + var resolver = http.RequestServices.GetRequiredService<AccessActorRoleResolver>(); |
| 75 | + var resolved = await resolver.ResolveAsync(tenant, user.UserKey, ct); |
| 76 | + |
| 77 | + actorRoles = resolved.ActorRoles; |
| 78 | + roleIds = resolved.RoleIds.ToArray(); |
| 79 | + } |
| 80 | + |
| 81 | + attributes = new ReadOnlyDictionary<string, object>( |
| 82 | + new Dictionary<string, object> |
| 83 | + { |
| 84 | + ["roles"] = roleIds |
| 85 | + }); |
| 86 | + } |
| 87 | + |
15 | 88 | return new AccessContext( |
16 | 89 | actorUserKey: user.IsAuthenticated ? user.UserKey : null, |
17 | | - actorTenant: http.GetTenant(), |
| 90 | + actorTenant: tenant, |
18 | 91 | isAuthenticated: user.IsAuthenticated, |
19 | 92 | isSystemActor: false, |
20 | 93 | actorChainId: null, |
21 | | - |
| 94 | + actorRoles: actorRoles, |
22 | 95 | resource: ResolveResource(action), |
23 | 96 | targetUserKey: null, |
24 | | - resourceTenant: http.GetTenant(), |
25 | | - |
| 97 | + resourceTenant: tenant, |
26 | 98 | action: action, |
27 | | - attributes: EmptyAttributes.Instance |
28 | | - ); |
| 99 | + attributes: attributes); |
29 | 100 | } |
30 | 101 |
|
31 | 102 | private static string ResolveResource(string action) |
|
0 commit comments