custom AuthorizeAttribute should be failing but API runs

286 views Asked by At

I have created a custom authorize attribute class for my application, to test if a user is allowed to access the API route. The user I am testing with has had all permissions that this class will test for removed, however the api is still running. What am I doing wrong?

UserActionsDictionary has tenant IDs as the keys and a list of strings for actions.

using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Application {
    public class HasActionAttribute : AuthorizeAttribute {

        public string Actions { get; set; }
        protected override bool AuthorizeCore(HttpContextBase httpContext) {
            UserCache userCache = HELPERS.GetCurrentUserCache();
            return userCache.UserActionsDictionary[userCache.CurrentTenantID.ToString()].Intersect(Actions.Split(',').ToList()).Any();
        }

        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) {
            filterContext.Result = new HttpUnauthorizedResult("Action not allowed for the current user");
        }
    }
}

And in the controller. I am testing what should be causing the authorize to fail within the route, it should never even make it in, but with breakpoints I am seeing that test is coming out to false.

[Authorize]
public class TestController : ApiController {

    [Route("api/Test/TestRoute")]
    [HttpGet]
    [HasAction(Actions="Test Action")]
    public dynamic Test(){
        UserCache userCache = HELPERS.GetCurrentUserCache();
        bool test = userCache.UserActionsDictionary[userCache.CurrentTenantID.ToString()].Intersect("Test Action".Split(',').ToList()).Any();
        return test;
    }
}

I see a lot of questions here on SO about similar topics, but none seem to address the issue I have here.

2

There are 2 answers

0
Andrew On BEST ANSWER

haim770 answered my issue mostly in the question comments, so I'll put the full answer here for others with similar issues.

I was inheriting the wrong AuthorizeAttribute. I needed to inherit from System.Web.Http not System.Web.MVC. The final code for the attribute is below.

using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Controllers;

namespace Application {
    public class HasActionAttribute : AuthorizeAttribute {

        public string Actions { get; set; }
        public override void OnAuthorization(HttpActionContext actionContext) {
            UserCache userCache = HELPERS.GetCurrentUserCache();
            List<string> actionsList = Actions.Split(',').Select(a=>a.Trim(' ')).ToList();
            if (!userCache.UserActionsDictionary[userCache.CurrentTenantID.ToString()].Intersect(actionsList).Any()) {
                HandleUnauthorizedRequest(actionContext);
            }
        }

        protected override void HandleUnauthorizedRequest(HttpActionContext filterContext) {
            filterContext.Response = new HttpResponseMessage(HttpStatusCode.Forbidden) { Content = new StringContent("Action not allowed for the current user") };
        }
    }
}
5
Yaser On

I think that you'd forgotten to put the:

GlobalFilters.Filters.Add(new HasActionAttribute()); 

in ~/App_Start/FilterConfig.cs.

The FilterConfig is used to manage global filters.

UPDATE:

And change you method to check for null parameter:

protected override bool AuthorizeCore(HttpContextBase httpContext) {
    if(string.IsNullOrWhiteSpace(Actions))
    {
        return true;
    }
    UserCache userCache = HELPERS.GetCurrentUserCache();
    return userCache.UserActionsDictionary[userCache.CurrentTenantID.ToString()].Intersect(Actions.Split(',').ToList()).Any();
}