HandleUnauthorizedRequest not overriding
Asked Answered
F

2

12

In my asp.net mvc3 application, I have a custom Authorization Attribute as seen below.

public class CustomAuthorize : AuthorizeAttribute
{
    public IAccountRepository AccountRepository { get; set; }

    public CustomAuthorize()
    {
        this.AccountRepository = new UserModel();
    }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        base.AuthorizeCore(httpContext);
        return AccountRepository.isEnabled(HttpContext.Current.User.Identity.Name);
    }

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) 
    {
        base.HandleUnauthorizedRequest(filterContext);
    }
}

I have the [CustomAuthorize] tag on my controller actions, and the AuthorizeCore method works fine - it performs the logic I want it to (making sure the account is actually enabled), and then returning as such.

However, the overridden HandleUnauthorizedRequest method, which as I understand it should allow me to control the behaviour of an unauthorized request, is not running at all. I put a breakpoint there, I put code in there, I access my application unauthorized, and the code never runs.

What am I missing?

EDIT: I did some more research and found a few other people who had this problem, but no solution unfortunately.

EDIT2: Sample code

[CustomAuthorize]
public class UserController: Controller
{
    public UserController() 
    {
        //do stuff here
    }
}

EDIT 3: @Fabio

Here's what I'm trying to do. I have a login page (forms auth) that works fine - it calls my custom login, and then calls my AuthorizeCore override. My application uses a large amount of ajax calls, and my eventual goal is for whenever a user is using the application, and the administrator disables them, making an ajax call after being disabled (though still being logged in) should log them out. However, in order to do this, i want to return a custom response if the user is making an ajax call, and for that, I need to ovverride HandleUnauthorizedRequest. But my Authorize Core (and by extension HandleUnauthorizedRequest) are being ignored if the user is logged in (despite the fact that I have customauthorize tags on all of my controller actions that the ajax is calling).

In short: I want to authorize the user on every request, not just the login request (which seems to be what the membership provider is doing right now)

Ferdelance answered 18/6, 2012 at 17:58 Comment(10)
Do you have any other attributes that inherit from AuthorizeAttribute? Do you have the AuthorizeAttribute set at the class level, or on a base class?Nisen
I have a custom membership provider, this class is declared in the same file. I have no other attributes that inherit from AuthorizeAttribute as far as I know.Ferdelance
Does a breakpoint placed in AuthorizeCore break, as expected?Nisen
@KyleTrauberman No it doesn't, that's the strange part.Ferdelance
Can you paste some code where you are using this attribute? It seems pretty trivial, but seeing the usage might shed some light on the problem.Nisen
@KyleTrauberman Done. Just to reiterate, the authorizecore override is being called in this context, so the code does work. It's just the handleunauthorizedrequest that doesn't do anything.Ferdelance
What happens if you decorate an action on the controller, and not the controller itself?Nisen
@KyleTrauberman I will find out for you tomorrow morning as I'm headed to bed. I think I did have some controller actions decorated as well to no avail, but I'll confirm tomorrow.Ferdelance
@KyleTrauberman Yeah, same thing. No matter what I do the method just isn't being called.Ferdelance
This may be a stupid question but is AccountRepository.isEnabled method returning false so that the HandleUnauthorizedRequest can be executed?Franza
F
8

I ended up changing my approach a fair bit. I implemented individual permissions checking, and then that caused AuthorizeCore to be called every time (and not be cached, which I guess was what was happening before).

Interestingly enough, putting a breakpoint on the HandleUnauthorizedRequest override still doesn't break, but putting it inside the method will. Strange, and threw me off for a bit, but I've solved it now.

Code if anyone is interested:

public class CustomAuthorize : AuthorizeAttribute
{
    public string Permissions { get; set; }

    private IAccountRepository AccountRepository { get; set; }        

    private string[] permArray { get; set; }

    private string reqStatus { get; set; }

    public CustomAuthorize()
    {
        this.AccountRepository = new UserModel();
    }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        base.AuthorizeCore(httpContext);

        if (Permissions != null) {
            permArray = Permissions.Trim().Split(' ');

            if (AccountRepository.isEnabled(httpContext.User.Identity.Name)) {
                this.reqStatus = "permission";
                return AccountRepository.hasPermissions(permArray);                     
            } else {
                return false;
            }
        } else {
            return AccountRepository.isEnabled(httpContext.User.Identity.Name);
        }
    }

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) 
    {
        if (this.reqStatus == "permission") {
            filterContext.Result = new RedirectResult(MvcApplication.eM.cause("no_permission", "redirect"));
        } else {
            base.HandleUnauthorizedRequest(filterContext);
        }
    }
}

And then I decorated the controller with this:

[CustomAuthorize(Permissions="test_perm")]

Ferdelance answered 21/6, 2012 at 19:50 Comment(0)
F
2

This may be a stupid answer/question but is AccountRepository.isEnabled method returning false so that the HandleUnauthorizedRequest can be executed?

If it's returning true, then the HandleUnauthorizedRequest method won't be executed.

Franza answered 19/6, 2012 at 15:2 Comment(1)
I think you may have stumbled upon something. It seems that the AuthorizeCore is only ever being called if the user is actually logged in already. So if I log out of the application, and navigate to my controller, it won't run my custom AuthorizeCore, it just redirects to the login page automatically. See my soon to come edit to my OP.Ferdelance

© 2022 - 2024 — McMap. All rights reserved.