using Connected.Entities; using Connected.Middleware; using Connected.Security.Authorization; using Connected.Security.Identity; using System.Collections.Immutable; using System.Security; namespace Connected.Services.Authorization; public abstract class ServiceAuthorizationMiddleware : MiddlewareComponent, IServiceAuthorizationMiddleware { protected ServiceAuthorizationMiddleware(IAuthorizationService authorizationService, IIdentityService identityService) { AuthorizationService = authorizationService; IdentityService = identityService; } protected IAuthorizationService AuthorizationService { get; } protected IIdentityService IdentityService { get; } public Task> ResolveClaims(ImmutableArray claims) { return OnResolveClaims(claims); } protected virtual Task> OnResolveClaims(ImmutableArray claims) { return Task.FromResult(claims); } public async Task Authorize(ServiceAuthorizationMiddlewareArgs args) where TArgs : IDto { await OnAuthorize(args); } protected virtual async Task OnAuthorize(ServiceAuthorizationMiddlewareArgs args) where TArgs : IDto { foreach (var claim in args.Claims) { var result = await AuthorizationService.Authorize(new AuthorizationArgs { User = IdentityService.CurrentUser?.Id, Claim = claim, Component = args.Context.Sender.GetType().Name, Method = args.Context.Method, Schema = new AuthorizationSchema { EmptyPolicy = EmptyPolicyBehavior.Alow, Strategy = AuthorizationStrategy.Pessimistic } }); if (!result.Success) throw new AccessViolationException($"{SR.PolicyAuthorizationFailed} ({result.Reason})"); } } public async Task Authorize(ServiceAuthorizationMiddlewareArgs args, TComponent component) where TArgs : IDto { return await OnAuthorize(args, component); } protected async Task OnAuthorize(ServiceAuthorizationMiddlewareArgs args, TComponent component) where TArgs : IDto { var entity = component as IEntity; var primaryKey = entity is null ? component.ToString() : entity.PrimaryKeyValue(); foreach (var claim in args.Claims) { var result = await AuthorizationService.Authorize(new AuthorizationArgs { User = IdentityService.CurrentUser?.Id, Claim = claim, Component = args.Context.Sender.GetType().Name, Method = args.Context.Method, Schema = new AuthorizationSchema { EmptyPolicy = EmptyPolicyBehavior.Alow, Strategy = AuthorizationStrategy.Pessimistic }, Entity = entity.EntityId(), PrimaryKey = primaryKey }); if (!result.Success) throw new SecurityException($"{SR.PolicyAuthorizationFailed} ({result.Reason})"); } return component; } }