ASP.NET MVC 5: Custom AuthorizeAttribute for custom authentication

In my previous post, I wrote about how to protect your web app from human errors by enforcing authentication by default.

Since that process involves global filters, you can use that to add your own custom authentication by extending the AuthorizeAttribute.

We ‘ll start by adding a new .cs file (I also added a folder Attributes for all custom attributes and extensions) with the following code (read the comments for explanation):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace MyNewProject.Attributes {

    [AttributeUsageAttribute( AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true )]
    public class myAuthorizeAttribute : AuthorizeAttribute {
        
        //Custom named parameters for annotation
        public string ResourceKey { get; set; }
        public string OperationKey { get; set; }

        //Called when access is denied
        protected override void HandleUnauthorizedRequest( AuthorizationContext filterContext ) {
            //User isn't logged in
            if ( !filterContext.HttpContext.User.Identity.IsAuthenticated ) {
                filterContext.Result = new RedirectToRouteResult(
                        new RouteValueDictionary( new { controller = "Account", action = "Login" } )
                );
            }
            //User is logged in but has no access
            else {
                filterContext.Result = new RedirectToRouteResult(
                        new RouteValueDictionary( new { controller = "Account", action = "NotAuthorized" } )
                );
            }
        }

        //Core authentication, called before each action
        protected override bool AuthorizeCore( HttpContextBase httpContext ) {
            var b = myMembership.Instance.Member().IsLoggedIn;
            //Is user logged in?
            if ( b )
                //If user is logged in and we need a custom check:
                if ( ResourceKey != null && OperationKey != null )
                    return ecMembership.Instance.Member().ActivePermissions.Where( x => x.operation == OperationKey && x.resource == ResourceKey ).Count() > 0;
            //Returns true or false, meaning allow or deny. False will call HandleUnauthorizedRequest above
            return b;
        }
    }
}

Then you can just use it from your controller like this:

    //No Annotation, user must be logged in
    public ActionResult DoSomething( [DataSourceRequest]DataSourceRequest request ) 
    
    //Custom authentication request
    [myAuthorizeAttribute(ResourceKey="SomeResource",OperationKey="SomeAction")]
    public ActionResult DoSomething( [DataSourceRequest]DataSourceRequest request ) 

    //No Authentication at all
    [AllowAnonymous]
    public ActionResult DoSomething( [DataSourceRequest]DataSourceRequest request ) 

* You should also read “MVC: Secure your web app” post to understand why no authorize annotation means authentication!

About these ads

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