MVC3 Custom AuthorizeAttribute

When coding websites in MVC3 it dosent take long before you realize you want a custom membership provider to handle your user logins. Once you have gotten this to work it is an even shorter time before you want to create your own custom attributes to apply to your Controller methods.

One example of a built in attribute is

[Authorize]

Adding this just before the Controller forces users to log in before they can use the specific part of the website the controller represents, redirecting them to the logon page before they can proceed.

But what if you wanted to make your own attribute that did something special that you could define?
Turns out its quite easy to do.

I Just finished making my own custom attribute that makes sure the user is in a specific role.

[CustomAuthorize(RequiredRole = "Admin")]

First off let me show you my models:

Here is a slimmed down version of my user model:

public class User : MembershipUser
    {
        public int ID { get; set; }
        public DateTime Created { get; set; }
        public DateTime LastLogin { get; set; }

        [Required]
        [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength =2)]
        public String username { get; set; }

        [Required]
        [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 2)]
        [DataType(DataType.Password)]
        public String password { get; set; }

        public virtual ICollection UserRoles { get; set; }

        public User()
        {
            UserRoles = new List();
        }

        public bool MemberOf(string RoleName)
        {
            return UserRoles.Count(r => r.RoleName == RoleName) > 0 ? true : false;
        }
}

As you can see my User model has a relation to a UserRole model:

    public class UserRole
    {
        public int ID { get; set; }
        public int RoleID { get; set; }
        public String RoleName { get; set; }
        public String Description { get; set; }

        public virtual ICollection Users { get; set; }

        public UserRole()
        {
            Users = new List();
        }
    }

In my example this role has been added

    new UserRole
    {
        RoleID = 10,
        RoleName = "Admin",
        Description = "The Administrators role"
    });

Using a membershipprovider similar to the one discussed in a previous post I have added a new user

                MembershipProvider Membership = new AccountProvider();
                MembershipCreateStatus createStatus;

                Membership.CreateUser("admin", "123123", null, null, null, true, null, out createStatus);
                UserRepository users = new UserRepository();

                User u = context.Users.First(us => us.username == "admin");

                if (u != null)
                {
                    UserRole ur = context.UserRoles.First(r => r.RoleID == 10);
                    u.UserRoles.Add(ur);
                }

Once we have something similar to that set up the actual attribute part to make sure a user is in a specific role is quite easy to set up. What we need is a properly named class that inherits from

AuthorizeAttribute

I created a new file called

HandleAuthorizeAttribute.cs

and wrote the following code in it:

    public class CustomAuthorizeAttribute : AuthorizeAttribute
    {
        DatabaseConnection _db = new DatabaseConnection ();
        public string RequiredRole;
        public int YourCustomValue;
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            if (httpContext == null) throw new ArgumentNullException("httpContext");
            if (httpContext.User.Identity.IsAuthenticated == false) return false;
            try
            {
                User user = _db.Users.Include("UserRoles").Single(u => u.username == httpContext.User.Identity.Name);
                return user.MemberOf(RequiredRole);
            }
            catch (Exception)
            {
                return false;
            }
        }
    }

And thats it, now you can use your new shiny tag to protect your pages :)

        [CustomAuthorize(RequiredRole = "Admin")]
        public ActionResult ProtectedPage()
        {
            return View();
        }
  • Quincy

    Came to yuor web blog through Delicious. You already know I will be subscribing to your rss feed.

  • Asics Saiko

    Very good article, I am browsing back again persistently to watch out for fresh news.

  • Clemente

    Good put up, We are checking back frequently to hunt for fresh news.

  • reseller hosting delhi

    I got what you mean , saved to fav, very nice site

  • Jay

    Thanks for the informative bolg. Im new to mvc3. How would I cater for multiple users roles in the custom attribute.
    [RoleAttribute(Roles=Constants.Administrator)]
    [RoleAttribute(Roles=Constants.OtherUser)]
    When doing it this way mvc3 expects the user to be in both roles. Please help

    • Jens

      You should be able to accomplish this by doing something similar to this:
      [CustomAuthorize(RequiredRole = "Admin, User")]

      And then replacing
      return user.MemberOf(RequiredRole);
      with
      string[] Roles = RequiredRole.Split(‘,’);
      foreach (string role in Roles)
      {
      if(role.Trim().Length > 0)
      if(user.MemberOf(role.Trim()) == true)
      return true
      }
      return false;