0

I have added a few custom claims to my user and I was wondering if I want to check if these claims exist on controller actions using attributes, I know that we can create a class and extend attribute from .Net and the general idea is to check if user has claim or not, I'm not really clear on the implementation.

Maybe something like this:

[AttributeUsage(AttributeTargets.All, Inherited = true, AllowMultiple = false)]
public class ClaimRequirementAttribute : Attribute
{
    public ClaimRequirementAttribute(string claimType)
    {
        new Claim(claimType, null);
    }
}
public class ClaimRequirementFilter
{
    public void OnAuthorization(HttpContext httpContext)
    {
        var hasClaim = httpContext.User.HasClaim(x => x.Type == 
        CapabilityClaims.CanReadSpore);

        if (!hasClaim)
        {

        }
    }
}
Gert Arnold
  • 93,904
  • 24
  • 179
  • 256
Asker
  • 77
  • 6
  • Are you using identity server? – Mohamad Mousheimish Jun 01 '20 at 11:11
  • @MohamadMousheimish yes – Asker Jun 01 '20 at 12:09
  • What do you want to do with that claim? for example do you want to deny access if the user does not have the claim? – A_kat Jun 01 '20 at 14:44
  • @A_kat yes but the idea is I want to do the check if has claim to revoke or give access in a class that extends attribute to be used an attribute i.e [claimCheck(claimType)] on the controller action – Asker Jun 02 '20 at 09:54
  • @A_kat yes if the the user does not have the claim i would return a forbid or something like that and if the user has the claim i would give access – Asker Jun 03 '20 at 10:26

2 Answers2

1

You can get the Claims of a specific user, using the GetClaimsAsync method of UserManager.

You can use the following method:

public class TestController : Controller
{
    private readonly UserManager<AppUser> _userManager;
    public TestController(UserManager<AppUser> userManager)
    {
        _userManager = userManager;
    }

    public CheckIfClaimsExist(string email)
    {
        var user = await _userManager.FindByEmailAsync(email);
        if(user != null)
        {
            var claims = await _userManager.GetClaimsAsync(user);
        }
    }
}

Note: AppUser class is a custom class which extends IdentityUser class from identity server.

Mohamad Mousheimish
  • 1,378
  • 2
  • 11
  • 36
  • thank you for your reply, but i was hoping for help in implementing this as an attribute to be used on the controller – Asker Jun 02 '20 at 10:17
0

After some long research i found this answer using filters which ended up being the best approach

[AttributeUsage(AttributeTargets.All, Inherited = true, AllowMultiple = true)]

public class ClaimRequirementAttribute : TypeFilterAttribute
{
    public ClaimRequirementAttribute(params string[] claimType) : base(typeof(ClaimRequirementFilter))
    {
        Arguments = new object[] { claimType };
    }
}

public class ClaimRequirementFilter : IAuthorizationFilter
{
    readonly string[] _claimTypes;

    public ClaimRequirementFilter(string[] claimTypes)
    {
        _claimTypes = claimTypes;
    }
    public void OnAuthorization(AuthorizationFilterContext authContext)
    {
        if (authContext == null)
        {
            throw new ArgumentNullException(nameof(authContext));
        }

        var user = authContext.HttpContext.User;
        var resourceId = authContext.RouteData.Values["id"].ToString();

        var claimType = _claimTypes
            .All(s => (user.Claims)
                .Any(c => c.Type == s && (c.Value == resourceId || c.Value == string.Empty)));

        if (user == null || !claimType)
        {
            authContext.Result = new ForbidResult();
        }

    }

Asker
  • 77
  • 6