Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC4 areas and forms authentication

I have an MVC4 application set up with multiple areas. Each area must have its own login page. Let's say for example I have the following areas:

Main Admin

How can I set it so that the "Main" area has a different login page to the "Admin" area? I'm thinking web.config is not the way to go on this.

Currently I have the following in my root web.config file:

<authentication mode="Forms">
  <forms loginUrl="~/Admin/Login" timeout="2880" protection="Encryption" />
</authentication>

However, I'm struggling to work out how to adapt this to MVC4 with areas.

Please help.

like image 997
Laurence Frost Avatar asked Dec 06 '13 13:12

Laurence Frost


2 Answers

I don't know if you can make it work with configuration files in each folder. Use that solution if you can. If you can't, here's a custom action filter that you can use:

public class AreaAuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        string area = filterContext.RouteData.Values.ContainsKey("area") 
                        ? filterContext.RouteData.Values["area"].ToString()
                        : null;

        if (area == "Admin")
        {
            RouteValueDictionary routeValues = new RouteValueDictionary 
            {
                {"controller" , "Login"},
                {"action" , "Index"},
                {"area" , "Admin"}
             };

            filterContext.Result = new RedirectToRouteResult("AdminAreaRoute", routeValues);
        }
        else if (area == "User")
        {
            RouteValueDictionary routeValues = new RouteValueDictionary 
            {
                {"controller" , "Login"},
                {"action" , "Index"},
                {"area" , "User"}
            };

            filterContext.Result = new RedirectToRouteResult("UserAreaRoute", routeValues);
        }

        base.HandleUnauthorizedRequest(filterContext);
    }
}

You may need to fix route names, I can't remember if ASP.NET MVC generated a route for each area. Then you can use it like this:

[AreaAuthorize]
public ViewResult Index()
{
    return View("Index");
}
like image 165
Ufuk Hacıoğulları Avatar answered Sep 20 '22 09:09

Ufuk Hacıoğulları


Many thanks to Ufuk Hacıoğulları for putting me on the right scent. My final solution was this:

public class AreaAuthorizeAttribute : AuthorizeAttribute
{
    private readonly string area;

    public AreaAuthorizeAttribute(string area)
    {
        this.area = area;
    }

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        string loginUrl = "";

        if (area == "Admin")
        {
            loginUrl = "~/Admin/Login";
        }
        else if (area == "Members")
        {
            loginUrl = "~/Members/Login";
        }

        filterContext.Result = new RedirectResult(loginUrl + "?returnUrl=" + filterContext.HttpContext.Request.Url.PathAndQuery);
    }
}
like image 30
Laurence Frost Avatar answered Sep 22 '22 09:09

Laurence Frost