Search code examples
asp.net-coreasp.net-core-webapiaop

Check User Authorization with Aspect Oriented Programming in Asp.Net Core 3.1 Web Api


I want to check user authorization in the api method.

Method responsible for get for an employee by id. So user should render this method if the user works the same company with employee. So I mean user CompanyId should be same with the Employee CompanyId.

Think about like this api method:

    public async Task<IActionResult> GetEmployeeById([FromRoute]int id)
    {
        try
        {   
            var entity = await _employeeRepository.GetAsync(p => p.Id == id);
            if (entity == null)
            {
                return NotFound();
            }

            //user's CompanyId should be same with Employee CompanyId
            var user = await _userManager.FindByIdAsync(User.Identity.Name);

            if (user.CompanyId != eployee.CompanyId)
            {
                return Unauthorized();
            }

            return Ok(entity);
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

I have to check user company in all api methods. So I want to do this by Aspect Oriented Programming.So method should be like this after AOP implementation:

 [CheckUserCompany]
 public async Task<IActionResult> GetEmployeeById([FromRoute]int id)
    {
        try
        {   
            var entity = await _employeeRepository.GetAsync(p => p.Id == id);
            if (entity == null)
            {
                return NotFound();
            }

            return Ok(entity);
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

How can I do this with Aspect Oriented Programming in Asp.Net Core 3.1 Web Api?

Thanks


Solution

  • You could customize a ActionFilter like below:

     public class CheckUserCompany:IActionFilter
    {
        private readonly ApplicationDbContext _dbcontext;
        private readonly UserManager<ApplicationUser> _userManager;
        public CheckUserCompany(ApplicationDbContext dbcontext, UserManager<ApplicationUser> userManager)
        {
            _dbcontext = dbcontext;
            _userManager = userManager;
        }
    
        // Do something before the action executes.
        public void OnActionExecuting(ActionExecutingContext context)
        {
            var id = (int)context.ActionArguments["id"];
            var employee = _dbcontext.Employee.Find(id);
            var user = _userManager.FindByNameAsync(context.HttpContext.User.Identity.Name);
    
            if (user.Result.CompanyId != employee.CompanyId)
            {
                throw new UnauthorizedAccessException();
            }
            return;
        }
    
        // Do something after the action executes.
        public void OnActionExecuted(ActionExecutedContext context)
        {
        }
    }
    

    If we want to use our filter as a service type on the Action or Controller level, we need to register it in the same ConfigureServices method but as a service in the IoC container:

    services.AddScoped<CheckUserCompany>();
    

    Finally, to use a filter registered on the Action or Controller level, we need to place it on top of the Controller or Action as a ServiceType:

    [ServiceFilter(typeof(CheckUserCompany))]
    public async Task<IActionResult> GetEmployeeById([FromRoute]int id)