problem:
when using global filter to authorize user with custom service function inside the IActionFilter
i have object reference Error for for the service instance.
public class GlobalActionFilter : IActionFilter
{
private readonly IUserAuthorizationService userAuthorizationService;
public GlobalActionFilter(IUserAuthorizationService userAuthorizationService)
{
this.userAuthorizationService = userAuthorizationService;
}
public void OnActionExecuted(ActionExecutedContext context)
{
}
public void OnActionExecuting(ActionExecutingContext context)
{
// our code before action executes
try
{
string user = context.HttpContext.User?.Claims?.FirstOrDefault(i => i.Type == "name")?.Value;
string tenantId = context.HttpContext.User?.Claims?.FirstOrDefault(i => i.Type == "tid")?.Value;
tenantId ??= context.HttpContext.User?.Claims?.FirstOrDefault(i => i.Type == "http://schemas.microsoft.com/identity/claims/tenantid")?.Value;
string subjectId = context.HttpContext.User.Claims?.FirstOrDefault(i => i.Type == "sub").Value;
Audit.Core.IAuditScope auditScope = context.HttpContext.GetCurrentAuditScope();
auditScope.SetCustomField("Username", user);
auditScope.SetCustomField("TenantName", tenantId);
var param = context.ActionArguments.SingleOrDefault(p => p.Key.ToLower()=="tenantid");
context.ActionArguments.TryGetValue("TenantId", out object actionTenantId);
if (actionTenantId != null)
{
if(int.TryParse(tenantId, out int loggedInUserTenantId))
{
if (!userAuthorizationService.CheckTenantAdminPolicyForLoggedInUser(subjectId, loggedInUserTenantId, (int)actionTenantId))
context.Result = new UnauthorizedObjectResult("user is unauthorized");
}
}
}
catch (System.Exception)
{
}
}
}
Startup configuration for MyGlobal Custom filter.
services.AddControllers(configure =>
{
AuditConfiguration.ConfigureAudit(services, Configuration);
AuditConfiguration.AddAudit(configure);
configure.Filters.Add(new GlobalActionFilter());
});
---------------------------------------------------------------------------
solution:
implement new class inherits from IFilterFactory and inject service for my global action filter inside.
public class AuthorizationFilterFactory : IFilterFactory
{
public bool IsReusable => false;
public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
{
// manually find and inject necessary dependencies.
var context = (IUserAuthorizationService)serviceProvider.GetService(typeof(IUserAuthorizationService));
return new GlobalActionFilter(context);
}
}
}
then Edit startup configuration for as follow
services.AddControllers(configure =>
{
AuditConfiguration.ConfigureAudit(services, Configuration);
AuditConfiguration.AddAudit(configure);
//configure.Filters.Add(new GlobalActionFilter());
configure.Filters.Add(new AuthorizationFilterFactory());
});
No comments:
Post a Comment