1

I have a custom AuthorizeAttribute which checks if a user can access a particular action:

public class UserCanAccessArea : AuthorizeAttribute
{
    readonly IPermissionService permissionService;

    public UserCanAccessArea() :
        this(DependencyResolver.Current.GetService<IPermissionService>()) { }

    public UserCanAccessArea(IPermissionService permissionService)
    {
        this.permissionService = permissionService;
    }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        string AreaID = httpContext.Request.RequestContext.RouteData.Values["AreaID"] as string;

        bool isAuthorized = false;

        if (base.AuthorizeCore(httpContext))
            isAuthorized = permissionService.UserCanAccessArea(AreaID, httpContext.User);

        return isAuthorized;
    }
}

The code simply checks that the User is authenticated, then checks the Users corresponding entry in an application specific database to determine if the User has access to the specified Area. Currently, this is simply a "CanAccessAreas" flag on the table.

The problem I am having is that when an Admin updates the "CanAccessAreas" flag for a User, the User still cannot access the area. Noted behaviour:

  • Logging out/in does not solve this for the User.
  • Running the code locally does not reproduce this behaviour.
  • Republishing the code solves the problem for the User until the flag is updated.
  • Each user is presented with a menu, which shows what they can access. This updates instantly when an Admin updates a Users flag.

It seems like the AuthorizeAttribute is caching the result but I'm unsure how to prevent this securely if this is the case.

James
  • 1,979
  • 5
  • 24
  • 52
  • It actually sounds like your IPermissionService is returning stale data. Perhaps your DI is set to only return a single instance per application lifetime? You should be able to put a breakpoint on your `AuthorizeCore` method to see that this is called per request. – Dan Apr 27 '15 at 16:56
  • The method is definitely called. I felt sure it couldnt be the data as the Users menu is updated immediately after an Admin updates the flag but you may be onto something as DI outside of my AuthorizeAttribute is taken care of by Unity (which I dont think works well with AuthorizeAttributes) – James Apr 27 '15 at 17:03
  • atleast I found easiest way to inject into AuthorizeAttribute is through Property Injections not through Constructor. So I think in your case too , it may not be injecting properly or using singleton of the IPermisionService or somehow caching IPermissionService – pjobs Apr 27 '15 at 17:34

1 Answers1

0

The constructor is only called when you call GetCustomAttributes, and MVC seems to call this only one time.

The solution is to get access to your service outside of the constructor.

e.g.:

public class UserCanAccessArea : AuthorizeAttribute
{
    public UserCanAccessArea()
    {
    }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        string AreaID = httpContext.Request.RequestContext.RouteData.Values["AreaID"] as string;

        bool isAuthorized = false;

        if (base.AuthorizeCore(httpContext))
        {
            var permissionService = DependencyResolver.Current.GetService<IPermissionService>();
            isAuthorized = permissionService.UserCanAccessArea(AreaID, httpContext.User);
        }

        return isAuthorized;
    }
}

I don't have experience with Unity, but same should be possible with Property Injection as @pjobs commented.

Christian Gollhardt
  • 16,510
  • 17
  • 74
  • 111