Wednesday, November 2, 2022

.netCore Global Filter with injected services inside.

 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