ASP.NET MVC 5: Custom authentication with OnActionExecuting
by George Kosmidis / Published 10 years ago, modified 5 years and 4 months ago
Although I prefer the AuthorizeAttribute approach, there is another simpler way with a base Controller and OnActionExecuting:
Let’s assume the following Controller:
public class MemberController : Controller {
public ActionResult Index() {
//Stuff for members only
}
}
All you need is a base controller with OnActionExecuting overridden, to check before each action for the proper rights…:
public class BaseController : Controller {
protected override void OnActionExecuting( ActionExecutingContext ctx ) {
//Check to see if we need to skip authentication
if ( ctx.ActionDescriptor.GetCustomAttributes( typeof( AllowAnonymousAttribute ), true ).Any()
|| ctx.ActionDescriptor.ControllerDescriptor.GetCustomAttributes( typeof( AllowAnonymousAttribute ), true ).Any() )
return;
//If it's not even authenticated redirect to a login action
// ...remember, you need [AllowAnonymous] on Login action to prevent an endless redirect loop
if ( !ctx.HttpContext.User.Identity.IsAuthenticated ) {
ctx.Result = new RedirectToRouteResult(
new RouteValueDictionary( new { controller = "Account", action = "Login" } )
);
return;
}
else {
//Get controller and action for custom, per action, validation
var controllerName = ctx.ActionDescriptor.ControllerDescriptor.ControllerName;
var actionName = ctx.ActionDescriptor.ActionName;
if( MyProject.Users.Where( o => o.Username = User.Identity.Name && ...can execute this action...).Count() == 0){
ctx.Result = new RedirectToRouteResult(
new RouteValueDictionary( new { controller = "Account", action = "NotAuthorized" } )
);
return;
}
}
}
}
And of course you need to change every Controller of your app to inherit from your base:
public class MemberController : BaseController {
public ActionResult Index() {
//Stuff for members only
}
[AllowAnonymous]
public ActionResult FreeAction() {
//Stuff for everybody
}
}