Override Authorize Attribute in ASP.NET MVC

.Netasp.net MvcSecurityAuthenticationAuthorize

.Net Problem Overview


I have an MVC controller base class on which I applied the Authorize attribute since I want almost all of the controllers (and their actions along) to be authorized.

However I need to have a controller and an action of another controller unauthorized. I wanted to be able to decorate them with the [Authorize(false)] or something but this is not available.

Any ideas?

.Net Solutions


Solution 1 - .Net

Edit: Since ASP.NET MVC 4 the best approach is simply to use the built-in AllowAnonymous attribute.

The answer below refers to earlier versions of ASP.NET MVC

You could create a custom authorisation attribute inheriting from the standard AuthorizeAttribute with an optional bool parameter to specify whether authorisation is required or not.

public class OptionalAuthorizeAttribute : AuthorizeAttribute
{
	private readonly bool _authorize;

	public OptionalAuthorizeAttribute()
	{
		_authorize = true;
	}

	public OptionalAuthorizeAttribute(bool authorize)
	{
		_authorize = authorize;
	}

	protected override bool AuthorizeCore(HttpContextBase httpContext)
	{
		if(!_authorize)
			return true;

                    return base.AuthorizeCore(httpContext);
	}
}

Then you can decorate your base controller with that attribute:

[OptionalAuthorize]
public class ControllerBase : Controller
{
}

and for any controllers you don't want authorisation simply use the override with a 'false' - e.g.

[OptionalAuthorize(false)]
public class TestController : ControllerBase
{
	public ActionResult Index()
	{
		return View();
	}
}

Solution 2 - .Net

It seems ASP.NET MVC 4 'fixed' this by adding an AllowAnonymous attribute.

David Hayden wrote about this :

[Authorize]
public class AccountController : Controller
{
    [AllowAnonymous]
    public ActionResult Login()
    {
        // ...
    }

    // ...
}

Solution 3 - .Net

My personal take on this would be to split the controller. Just create another controller For the actions you don't need authentication.

Or you could have :

  • BaseController
    doesn't require authentication - here you have all your "base stuff" :).

  • BaseAuthController : BaseController
    all actions here require authentication.

That way you can have authentication when you want , just by deriving from a specific class.

Solution 4 - .Net

If you just want one action to be unauthorized on an otherwise authorized controller you can do something like this:

public class RequiresAuthorizationAttribute : ActionFilterAttribute
{
	private readonly bool _authorize;

	public RequiresAuthorizationAttribute()
	{
		_authorize = true;
	}

	public RequiresAuthorizationAttribute(bool authorize)
	{
		_authorize = authorize;
	}

	public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
		var overridingAttributes = filterContext.ActionDescriptor.GetCustomAttributes(typeof (RequiresAuthorizationAttribute), false);

		if (overridingAttributes.Length > 0 && overridingAttributes[0] as RequiresAuthorizationAttribute != null && !((RequiresAuthorizationAttribute)overridingAttributes[0])._authorize)
			return;

		if (_authorize)
		{
			//redirect if not authenticated
			if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
			{
				//use the current url for the redirect
				var redirectOnSuccess = filterContext.HttpContext.Request.Url.AbsolutePath;

				//send them off to the login page
				//var redirectUrl = string.Format("?RedirectUrl={0}", redirectOnSuccess);
				var loginUrl = LinkBuilder.BuildUrlFromExpression<HomeController>(filterContext.RequestContext, RouteTable.Routes,
				                                                                  x => x.Login(redirectOnSuccess));
				filterContext.HttpContext.Response.Redirect(loginUrl, true);
			}
		}
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAndrei R&#238;neaView Question on Stackoverflow
Solution 1 - .NetSteve WillcockView Answer on Stackoverflow
Solution 2 - .NetAndrei RîneaView Answer on Stackoverflow
Solution 3 - .NetsirroccoView Answer on Stackoverflow
Solution 4 - .NetpondermaticView Answer on Stackoverflow