Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Web API Authorize Attribute not working on Action

I am using the [Authorize] attribute on my WebAPI controller action and it's always coming back unauthorized.

Here is my action

    [Authorize(Roles = "Admin")]
    public IQueryable<Country> GetCountries()
    {
      return db.Countries;
    }

Here is where I am setting the Authorization in a Global MessageHandler. This is for testing I'm putting in a test user.

public class AuthenticationHandler1 : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {

        if (!HttpContext.Current.User.Identity.IsAuthenticated)
        {
            HttpContext.Current.User = TestClaimsPrincipal();
        }


        return base.SendAsync(request, cancellationToken);
    }

    private ClaimsPrincipal TestClaimsPrincipal()
    {

        var identity = new ClaimsIdentity(HttpContext.Current.User.Identity.AuthenticationType);
        identity.AddClaim(new Claim(ClaimTypes.Name, "some.user"));
        identity.AddClaim(new Claim(ClaimTypes.Role, "Admin"));
        identity.AddClaim(new Claim(ClaimTypes.Role, "Supervisor"));
        var testIdentity = new ClaimsIdentity(identity);

        var myPrincipal = new ClaimsPrincipal(testIdentity);

        return myPrincipal;
    }
}

Registered in Global.asax.cs in Application_Start

GlobalConfiguration.Configuration.MessageHandlers.Add(new MyProject.AuthenticationHandler1());

It keeps showing this for a message

{"Message":"Authorization has been denied for this request."}
like image 681
Heinrich Avatar asked Jan 06 '15 18:01

Heinrich


People also ask

How does the Authorize attribute work?

Web API provides a built-in authorization filter, AuthorizeAttribute. This filter checks whether the user is authenticated. If not, it returns HTTP status code 401 (Unauthorized), without invoking the action. We can apply the filter globally, at the controller level, or at the level of individual actions.

What is action name attribute in Web API?

ActionName attribute is an action selector which is used for a different name of the action method. We use ActionName attribute when we want that action method to be called with a different name instead of the actual name of the method.


1 Answers

I made a Custom Authorization Attribute and it works.

public class AuthorizationAttribute : System.Web.Http.AuthorizeAttribute
{
    public string Roles { get; set; }
    protected override bool IsAuthorized(HttpActionContext actionContext)
    {
        ClaimsPrincipal currentPrincipal = HttpContext.Current.User as ClaimsPrincipal;
        if (currentPrincipal != null && CheckRoles(currentPrincipal))
        {
            return true;
        }
        else
        {
            actionContext.Response =
                new HttpResponseMessage(
                System.Net.HttpStatusCode.Unauthorized)
                {
                    ReasonPhrase = "Some message"
                };
            return false;
        }
    }

    private bool CheckRoles(ClaimsPrincipal principal)
    {
        string[] roles = RolesSplit;
        if (roles.Length == 0) return true;
        return roles.Any(principal.IsInRole);
    }

    protected string[] RolesSplit
    {
        get { return SplitStrings(Roles); }
    }

    protected static string[] SplitStrings(string input)
    {
        if(string.IsNullOrWhiteSpace(input)) return new string[0];
        var result = input.Split(',').Where(s=>!String.IsNullOrWhiteSpace(s.Trim()));
        return result.Select(s => s.Trim()).ToArray();
    }
}

Use it like this

[AuthorizationAttribute(Roles = "SomeRole,Admin")]    
public IQueryable<Country> GetCountries()
    {
     }
like image 151
Heinrich Avatar answered Sep 30 '22 12:09

Heinrich