It is the implementation of the OnAuthorization
method of AuthorizeAttribute
that scans for AllowAnonymousAttribute
. So, you must either not override this method or re-implement this check if you want that part to work. Since you have only provided a cut-down implementation of AuthorizeAttribute
, it cannot be assumed that you are not overriding this method (and thus overriding the logic that makes the check).
Also, your example controller doesn't actually show usage of the AllowAnonymousAttribute
. Instead, it sets a property named AllowAnonymous
. If you expect anonymous users to reach that action method, you should decorate it with the attribute that MVC is actually scanning for.
[AuthorizePublic(Sites = AuthSites.Corporate)]
public class CorporateController : SecuredController
{
[AllowAnonymous]
public ActionResult Login(string returnUrl)
{
ViewBag.ReturnUrl = returnUrl;
return View();
}
}
Alternatively, if you need to customize the AllowAnonymous
behavior in some way, you can keep using the property you have, but you have to implement the Reflection code yourself to scan for AuthorizePublic
and check the AllowAnonymous
property.
public class AuthorizePublic : AuthorizeAttribute
{
public AuthSites Sites { get; set; }
public bool AllowAnonymous { get; set; }
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
var actionDescriptor = httpContext.Items["ActionDescriptor"] as ActionDescriptor;
if (actionDescriptor != null)
{
AuthorizePublic attribute = GetAuthorizePublicAttribute(actionDescriptor);
if (attribute.AllowAnonymous)
return true;
var sites = attribute.Sites;
// Logic
}
return true;
}
public override void OnAuthorization(AuthorizationContext filterContext)
{
// Pass the current action descriptor to the AuthorizeCore
// method on the same thread by using HttpContext.Items
filterContext.HttpContext.Items["ActionDescriptor"] = filterContext.ActionDescriptor;
base.OnAuthorization(filterContext);
}
// Gets the Attribute instance of this class from an action method or contoroller.
// An action method will override a controller.
private AuthorizePublic GetAuthorizePublicAttribute(ActionDescriptor actionDescriptor)
{
AuthorizePublic result = null;
// Check if the attribute exists on the action method
result = (AuthorizePublic)actionDescriptor
.GetCustomAttributes(attributeType: typeof(AuthorizePublic), inherit: true)
.SingleOrDefault();
if (result != null)
{
return result;
}
// Check if the attribute exists on the controller
result = (AuthorizePublic)actionDescriptor
.ControllerDescriptor
.GetCustomAttributes(attributeType: typeof(AuthorizePublic), inherit: true)
.SingleOrDefault();
return result;
}
}
AuthorizeAttribute
implements both Attribute
and IAuthorizationFilter
. With that in mind, the IAuthorizationFilter
part of AuthorizeAttribute
is a different runtime instance of the class than the Attribute
part. So the former must use Reflection to read the property of the latter in order for it to work. You can't just read the AllowAnonymous
property from the current instance and expect it to work, because you are setting the value in the attribute and the code is executing in the filter.
MVC and Web API are completely separate frameworks with their own separate configuration even though they can co-exist in the same project. MVC will completely ignore any controllers or attributes defined in Web API and vise versa.
[AllowAnonymous]
on an Action method does not override the Authorization attribute in your case? – Marco