Search code examples
asp.net-mvcwebformsowiniis-expresskatana

location path="" deny users="?" prevents access to domain root ("/") instead of showing RouteConfig default


I am using Katana to secure my site, along with location paths in web.config (as the site is a mixture of ASP.Net web forms and MVC).

My default route is configured like this to allow the login page to be displayed when accessing the domain root (e.g. www.example.com should show the login page at www.example.com/Public/Login):

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Public", action = "Login", id = UrlParameter.Optional }
        );
    }

Web.config is set to grant access to the login controller URL, but deny everything else that isn't authorized:

<location path="Public/Login">
    <system.web>
        <authorization>
            <allow users="*" />
        </authorization>
    </system.web>
</location>

<location path="">
    <system.web>
        <authorization>
            <deny users="?" />
        </authorization>
    </system.web>
</location>

This works fine except for www.example.com. Locally using IISExpress, these URL's:

https://localhost:44374
https://localhost:44374/

redirect to:

https://localhost:44374/Public/Login?ReturnUrl=%2F

This is incorrect, as / should be accessible to anonymous users based on the default RouteConfig MapRoute default.

Can anyone please advise what I'm doing wrong? Is there any way to grant access when only the root is accessed for a domain?


Solution

  • After trying around a dozen suggestions from this site, I finally found this to be the only solution that worked in my case. I'm not sure whether a mix of webforms and MVC controllers causes this issue (routing conflicts?), but adding this to global.asax worked perfectly:

    namespace MyApplicationNamespace
    {
        public class MyApplicationName : System.Web.HttpApplication
        {
            protected void Application_Start()
            {
                // leave as is - left here to clarify where new method needs adding
            }
    
            protected void Application_BeginRequest(object sender, EventArgs e)
            {
                if(Request.AppRelativeCurrentExecutionFilePath == "~/")
                {
                    HttpContext.Current.RewritePath("/Public/Login"); // the MVC login controller/action
                }
            }
        }
    }