Reputation: 83
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.
Upvotes: 1
Views: 7206
Reputation: 83
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();
}
}
}
Upvotes: 2