Custom user authorization based with roles in asp.net mvc

I have created a custom authentication and authorisation for my users.The problem I am facing is how to get mvc to check that role from inside my users table matches the [Authorize(Role)] on my controller so as to set httpauthorised to true.Below is my customauthorise class.

 [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public class CustomAuthorizeAttribute : AuthorizeAttribute 
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        base.OnAuthorization(filterContext);
        if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            filterContext.Controller.TempData["ErrorDetails"] = "You must be logged in to access this page";
            filterContext.Result = new RedirectResult("~/User/Login");
            return;
        }

        if (filterContext.HttpContext.Request.IsAuthenticated)
        {
            using (var db = new GManagerDBEntities())
            {
                var authorizedRoles = (from u in db.Users
                                       where u.Username == filterContext.HttpContext.User.Identity.Name
                                       select u.Role).FirstOrDefault();
                Roles = String.IsNullOrEmpty(Roles) ? authorizedRoles.ToString() : Roles;
            }
        }

        if (filterContext.Result is HttpUnauthorizedResult)
        {
            filterContext.Controller.TempData["ErrorDetails"] = "You do nat have necessary rights to access this page";
            filterContext.Result = new RedirectResult("~/User/Login");
            return;
        }

    }
    public CustomAuthorizeAttribute(params object[] roles)
    {
        if (roles.Any(r => r.GetType().BaseType != typeof(Enum)))
            throw new ArgumentException("roles");

        this.Roles = string.Join(",", roles.Select(r => Enum.GetName(r.GetType(), r)));
    }
}

below is my controller with decoration
 [CustomAuthorize(Role.Administrator)]
    [HttpGet]
    public ActionResult CreateEmployees()
    {
        return View();
    }

and my enum for role
public enum Role
{
    Administrator = 1,
    UserWithPrivileges = 2,
    User = 3,
}

and model
public class UserModel
{
    public int UserID { get; set; }
    [Required]
    [Display(Name="Username:")]
    public string Username { get; set; }
    [Required]
    public string Password { get; set; }
    public int Role { get; set; }
}

see pastie for clear view pastie

links I have viewed in trying to solve this among others but I cant seem to piece it togetherMVC 3 Authorize custom roles
http://forums.asp.net/p/1573254/3948388.aspx

Customized authorization attribute in MVC 4 with Roles

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

using the link shared by @VikasRana http://www.codeproject.com/Articles/578374/AplusBeginner-splusTutorialplusonplusCustomplusF

I got rid of my enum Role and my method

public CustomAuthorizeAttribute(params object[] roles)
    { ...}

I then changed Role in my model to be a string e.g. User.Role=”Admin” instead of int.
In my onAuthorization method I changed it to:
` public override void OnAuthorization(AuthorizationContext filterContext)
    {
        base.OnAuthorization(filterContext);
        if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            filterContext.Controller.TempData["ErrorDetails"] = "You must be logged in to access this page";
            filterContext.Result = new RedirectResult("~/User/Login");
            return;
        }
        if (filterContext.Result is HttpUnauthorizedResult)
        {
            filterContext.Controller.TempData["ErrorDetails"] = "You don't have access rights to this page";
            filterContext.Result = new RedirectResult("~/User/Login");
            return;
        }
        }

and in my global.asax added this.
protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
    {
        if (FormsAuthentication.CookiesSupported == true && Request.IsAuthenticated== true)
        {
            if (Request.Cookies[FormsAuthentication.FormsCookieName] != null)
            {
                try
                {
                    //let us take out the username now                
                    string username = FormsAuthentication.Decrypt(Request.Cookies[FormsAuthentication.FormsCookieName].Value).Name;
                    string roles = string.Empty;

                    using (GManagerDBEntities db = new GManagerDBEntities())
                    {
                        User user = db.Users.SingleOrDefault(u => u.Username == username);

                        roles = user.Role;
                    }
                    //let us extract the roles from our own custom cookie
                    //Let us set the Pricipal with our user specific details
                    HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(
                      new System.Security.Principal.GenericIdentity(username, "Forms"), roles.Split(';'));
                }
                catch (Exception)
                {
                    //something went wrong
                }
            }
        }
    }

Above method is not ideal though.It gets run for every simple page request about 3 times or more.

So here is solution 2:better solution
Implement a custom role provider since we are already using custom role implementation.Simply follow this linkhttp://techbrij.com/custom-roleprovider-authorization-asp-net-mvc

Method 2

Thanks Gotalove for this method in Global.asax. Here is some more help for anyone trying to do a custom Forms Authentication (FormsAuthentication, FormsAuthenticationTicket) using entity framework.

Login Controller
SetAuthTicket

protected void GetRoles(int UserID)
    {
        var db = new ResearchSurveysEntities();
        string[] getRoles = { };
        try
        {
            var query =

                from p in db.UserProfiles
                join i in db.webpages_UsersInRoles on p.UserId equals i.UserId
                join r in db.webpages_Roles on i.RoleId equals r.RoleId
                where p.UserId == UserID
                select new { p.UserId, r.RoleName };

            if (query.Count() > 0)
            {

                List<string> gRoles = new List<string>();
                foreach (var item in query)
                {
                    gRoles.Add(item.RoleName);
                }
                getRoles = gRoles.ToArray();
            }
            roles = String.Join("|", getRoles);
        }
        catch (Exception ex)
        {
            WebUtilities wu = new WebUtilities();

            wu.NotifyWebmaster(ex.ToString(), "Get roles for AdminUserID: " + UserID.ToString(), string.Empty, "Login Error");


        }
        finally
        {
            db.Dispose();
        }
    }

WebConfig
<authentication mode="Forms">
  <forms loginUrl="~/Account/Login" timeout="2880" />
</authentication>

Global.asax (From above example)
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
    {
        HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
        if (authCookie == null || authCookie.Value == "")
            return;

        FormsAuthenticationTicket authTicket;
        try
        {
            authTicket = FormsAuthentication.Decrypt(authCookie.Value);
        }
        catch
        {
            return;
        }

        // retrieve roles from UserData
        string[] roles = authTicket.UserData.Split('|');

        if (Context.User != null)
            Context.User = new GenericPrincipal(Context.User.Identity, roles);
    }


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x