You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Connected.Framework/Connected.Services/Authorization/ServiceAuthorizationMiddlew...

95 lines
2.8 KiB

2 years ago
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<ImmutableArray<string>> ResolveClaims(ImmutableArray<string> claims)
{
return OnResolveClaims(claims);
}
protected virtual Task<ImmutableArray<string>> OnResolveClaims(ImmutableArray<string> claims)
{
return Task.FromResult(claims);
}
public async Task Authorize<TArgs>(ServiceAuthorizationMiddlewareArgs<TArgs> args) where TArgs : IDto
{
await OnAuthorize(args);
}
protected virtual async Task OnAuthorize<TArgs>(ServiceAuthorizationMiddlewareArgs<TArgs> 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<TComponent> Authorize<TArgs, TComponent>(ServiceAuthorizationMiddlewareArgs<TArgs> args, TComponent component)
where TArgs : IDto
{
return await OnAuthorize(args, component);
}
protected async Task<TComponent> OnAuthorize<TArgs, TComponent>(ServiceAuthorizationMiddlewareArgs<TArgs> 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;
}
}