Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I implement Claims-Based Authorization with ASP.NET WebAPI without using Roles?

People also ask

How would you implement claims based authentication in .NET Core?

The claims-based authorization works by checking if the user has a claim to access an URL. In ASP.NET Core we create policies to implement the Claims-Based Authorization. The policy defines what claims that user must process to satisfy the policy. We apply the policy on the Controller, action method, razor page, etc.

How do I create a custom authorization filter in Web API?

To implement a custom authorization filter, we need to create a class that derives either AuthorizeAttribute , AuthorizationFilterAttribute , or IAuthorizationFilter . AuthorizeAttribute : An action is authorized based on the current user and the user's roles.


You can achieve that if you override the Authorize attribute. In your case it should be something like this:

public class ClaimsAuthorize : AuthorizeAttribute
{
    public string SubjectID { get; set; }
    public string LocationID { get; set; }

    protected override bool IsAuthorized(HttpActionContext actionContext)
    {
        ClaimsIdentity claimsIdentity;
        var httpContext = HttpContext.Current;
        if (!(httpContext.User.Identity is ClaimsIdentity))
        {
            return false;
        }      

        claimsIdentity = httpContext.User.Identity as ClaimsIdentity;
        var subIdClaims = claimsIdentity.FindFirst("SubjectId");
        var locIdClaims = claimsIdentity.FindFirst("LocationId");
        if (subIdClaims == null || locIdClaims == null)
        {
            // just extra defense
            return false;
        }

        var userSubId = subIdClaims.Value;
        var userLocId = subIdClaims.Value;

        // use your desired logic on 'userSubId' and `userLocId', maybe Contains if I get your example right?
        if (!this.SubjectID.Contains(userSubId) || !this.LocationID.Contains(userLocId))
        {
            return false;
        }

        //Continue with the regular Authorize check
        return base.IsAuthorized(actionContext);
    } 
}

In your controller that you wish to restrict access to, use the ClaimsAuthorize attribute instead of the normal Authorize one:

[ClaimsAuthorize(
    SubjectID = "1,2",
    LocationID = "5,6,7")]
[RoutePrefix("api/Content")]
public class ContentController : BaseController
{
     ....
}