kez
kez

Reputation: 2313

Role-Based Authentication with aspnet identity in ASP.NET MVC 4

I'm creating ASP.NET MVC 4 Internet Application.

In that Application I created Login Page that any user can log in to, then I allowed to redirect user to different pages based on their role.

ASP.NET Identity is the membership system here.

This is my Login Controller method:

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
    if (ModelState.IsValid)
    {
        var user = await UserManager.FindAsync(model.UserName, model.Password); 

        if (user != null)
        {
            if (user.ConfirmedEmail == true)
            {

                await SignInAsync(user, model.RememberMe);

                if (String.IsNullOrEmpty(returnUrl))
                {
                    if (UserManager.IsInRole(user.Id, "HEC_Admin"))
                    {
                        return RedirectToAction("Index", "HEC");
                    }
                    //role Admin go to Admin page
                    if (UserManager.IsInRole(user.Id, "HEI_User"))
                    {
                        return RedirectToAction("Index", "HEI");
                    }
                }

                else
                {
                    return RedirectToLocal(returnUrl);
                }


            }
            else
            {
                ModelState.AddModelError("", "Confirm Email Address.");
            }
        }
        else
        {
            ModelState.AddModelError("", "Invalid username or password.");
        }
    }
    // If we got this far, something failed, redisplay form
    return View(model);
}

This is HEI Controller Class:

public class HEIController : Controller
{
    //
    // GET: /HEI/

   [Authorize(Roles = "HEI_User")]
    public ActionResult Index()
    {
        return View();
    }



}

This is my HEC Controller Class:

     public class HECController : Controller

    {
        //
        // GET: /HEC/
       [Authorize(Roles = "HEC_Admin")]
       public ActionResult Index()
        {
            return View();
        }
   }

when I remove [Authorize(Roles = "HEC_Admin")] above the index action in HECController class and when I remove [Authorize(Roles = "HEC_User")] above the index action in HEIController class this is working fine,

but then How restrict unauthorized access to these pages?

Upvotes: 2

Views: 4786

Answers (1)

bitbruno
bitbruno

Reputation: 36

I had the same problem as you and I still don't know the reason why it happens. What I did was to create my own custom Authorization Attribute and check the Roles myself.

public class CustomAuthorizationAttribute : AuthorizeAttribute
{
    public string IdentityRoles
    {
        get { return _identityRoles ?? String.Empty; }
        set
        {
            _identityRoles = value;
            _identityRolesSplit = SplitString(value);
        }
    }

    private string _identityRoles;
    private string[] _identityRolesSplit = new string[0];

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        //do the base class AuthorizeCore first
        var isAuthorized = base.AuthorizeCore(httpContext);
        if (!isAuthorized)
        {
            return false;
        }
        if (_identityRolesSplit.Length > 0)
        {
            //get the UserManager
             using(var um = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext())))
            {
                var id = HttpContext.Current.User.Identity.GetUserId();
                //get the Roles for this user
                var roles = um.GetRoles(id);
                //if the at least one of the Roles of the User is in the IdentityRoles list return true
                if (_identityRolesSplit.Any(roles.Contains))
                {
                    return true;
                }
            }
            return false;
        }
        else
        {
            return true;
        }

    }

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        //if the user is not logged in use the deafult HandleUnauthorizedRequest and redirect to the login page
        if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            base.HandleUnauthorizedRequest(filterContext);
        }
        else
        //if the user is logged in but is trying to access a page he/she doesn't have the right for show the access denied page
        {
            filterContext.Result =  new RedirectResult("/AccessDenied");
        }
    }

    protected static string[] SplitString(string original)
    {
        if (String.IsNullOrEmpty(original))
        {
            return new string[0];
        }

        var split = from piece in original.Split(',')
                    let trimmed = piece.Trim()
                    where !String.IsNullOrEmpty(trimmed)
                    select trimmed;
        return split.ToArray();
    }
}

I also added the HandleUnauthorizedRequest method to redirect to a appropriated page if the user has is logged in but has no access to this action or controller

To use it just do this:

[CustomAuthorization(IdentityRoles = "HEI_User")]
public ActionResult Index()
{
    return View();
}

Hope it helps.

Upvotes: 2

Related Questions