0

I googled this and nothing was found, so I would like to know from those who use DotNet Core for a longer time than myself.

I am now to DotNet core. I am currently creating an App just for the sake of practicing. I noticed that in most of my Apis' Actions, I am verifying the passed in UserId against claims NameIdentifier (that is the logged in user id).

I am doing like so:

        if (userId != int.Parse(User.FindFirst(ClaimTypes.NameIdentifier).Value))
        {
            return Unauthorized();
        }

But now thinking, it is getting a bit too repetitive. Is there a way of using an Attribute instead?

Something like:

    [AuthorizeUser(UserId = userid)]
    [HttpGet]
    public async Task<IActionResult> GetSomething(int userId)
    {
            //Custom code ...
    }

And then create my Authorize Attribute:

public class AuthorizeUser : AuthorizeAttribute, IAuthorizationFilter
{
    public AuthorizeUser(params string[] args)
    {
        Args = args;
    }

    public string[] Args { get; }

    public void OnAuthorization(AuthorizationFilterContext context)
    {
        //Custom code ...
    }
}

This way I would check for the user id passed in the "api/user/{userId}" in a single place for all my Actions.

Or there is another way of making my code look nicer and with less copy and paste?

Thank you in advance.

RNA
  • 63
  • 2
  • 8
  • This could be helpful https://stackoverflow.com/questions/31464359/how-do-you-create-a-custom-authorizeattribute-in-asp-net-core – Karan Jul 30 '20 at 13:01

1 Answers1

2

I was able to solve my problem by doing the following:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class UserAuthorizationAttribute : AuthorizeAttribute, IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationFilterContext context)
    {
        // Here I can get userId from my params.
        var userId = context.RouteData.Values["userId"].ToString();

        // It is then being checked against current user claims.
        // The user is only authorized if the userId is equals to ClaimsType.Value and claims Type is equals to NameIdentifier. 
        var isUserAuthorized = context.HttpContext.User.Claims.Any(c => c.Type == ClaimTypes.NameIdentifier && c.Value == userId);
        
        if (!isUserAuthorized)
        {
            context.Result = new UnauthorizedResult();
        }
    }
}
RNA
  • 63
  • 2
  • 8
  • 2
    Could you please show how you added this to the controller action/method? – Sherman Jun 09 '21 at 19:02
  • 1
    @Sherman Just do `[UserAuthorization]` on either the controller `class` or each action method. Alternatively, as this is also an `IAuthorizationFilter` you can register it in your `Startup.ConfigureServices` method, via `AddMvc( o => o.Filters.Add( new UserAuthorizationAttribute() ) )`. – Dai Nov 17 '22 at 04:42