.netasp.net-core.net-coreattributesaction-filter

Change Request in ActionFilter By Property attributes


I am coding a .Net core API that serves administrators and employees. These people see the same interface.

The only difference is that the manager can view the profile of other employees. The employee can only view his own profile. I am using JWT. I have completed the development for the administrator section.

I want to use the same APIs in the employee section as well. But in this section, I need to get employeeId from JWT, not from the request.

I created an attribute for the fields representing the employeeId. Example:

public async Task<ActionResult<AddressDto>> Get(long deciderType, [EmployeeId] long deciderId)

I want to have an action filter, in that action filter if it has the desired role, I want to give the employeeId in JWT to the request variable that has this attribute. In this case to deciderId. Is this possible? I could not find a way to filter the request parameters by attribute.

Or is there a better way to do this? I can do these operations in different APIs with the same business but I am not sure if this is the right way


Solution

  • It's better to separate your Get APIs and set Authrozie Attribute with Role Admin for your administrator, and also one another Get for employees.

    If you have created your JWT like this

    var tokenDescriptor = new SecurityTokenDescriptor
    {
      Subject = new ClaimsIdentity(new Claim[]
                {
                    new Claim(ClaimTypes.Name, user.Id.ToString())
                }),
      Expires = DateTime.UtcNow.AddDays(7),
      SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), 
      SecurityAlgorithms.HmacSha256Signature)
    };
    

    Now in your Get method which belongs to the employee, you do not need to send EmployeeId and you can get it from the JWT token

    var claimsIdentity = this.User.Identity as ClaimsIdentity;
    var userId = claimsIdentity.FindFirst(ClaimTypes.Name)?.Value;
    

    In conclusion, you would have two Get endpoints.

    For Administrator

     [Authorize(Role=RolesEnumeration.Admin)]
     public async Task<IActionResult<AddressDto>> Get()
     {
           //get all addresses from the DB by pagination
     }
    

    And for employees

    public async Task<IActionResult<AddressDto>> Get()
     {
         var claimsIdentity = this.User.Identity as ClaimsIdentity;
         var userId = claimsIdentity.FindFirst(ClaimTypes.Name)?.Value;
    
         //get employee address from the DB by userId
     }