ASP.NET MVC 5: Custom authentication with OnActionExecuting

Although i prefer the AuthorizeAttribute solution, there is an other 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 and 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 each and every Controller to inherit from your base:

public class MemberController : BaseController {
    public ActionResult Index() {
       //Stuff for members only
    }

    [AllowAnonymous]
    public ActionResult FreeAction() {
       //Stuff for everybody
    }
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s