George Kosmidis

Microsoft MVP | Speaks of Azure, AI & .NET | Founder of Munich .NET
Building tomorrow @
slalom
slalom

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
    }
}

This page is open source. Noticed a typo? Or something unclear?
Edit Page Create Issue Discuss
Microsoft MVP - George Kosmidis
Azure Architecture Icons - SVGs, PNGs and draw.io libraries