Web.config allow location access for specific user

asp.netpermissionsweb-config

I have a webserver from where users can download files that are specific for each user. To be sure each user can only download its own files they must authenticate via Basic-Authentication. So for each user there is a windows-account on the server that has read permissions to the user specific folder.

Now I want to move this functionality to another server. I do not want to create windows accounts for the users but still keep the Basic-Authentication. So I use the Custom Basic Authentication HTTP Module in combination with a Custom MembershipProvider that lets me define users in the web.config.

The authentication works quite fine but after logging in with either jack or jill (see web.config) I'm able to access both locations Dir1 and Dir2. This is also the case if I comment out the <allow users="jack" /> part in the location tags.

Additional Info:
I created a Default.aspx file and added a

<% Response.Write(HTTPContext.Current.User.Identity.Name) %>

which returns the correct user name depending on who logged in.

<% Response.Write(HTTPContext.Current.User.Identity.IsAuthenticated) %>

returns True.

What do I have to do that only jack is able to access (= download files from) Dir1 and only jill is able to access (=download files from) Dir2 but not the other way round?

EDIT: I tried to add web.config files for each subdirectories instead of the location tags as mentioned by utkai – with the same result. Every user can access any directory.

Here is my Web.config file:

<configuration>
<system.webServer>
    <modules>
        <add name="CustomBasicAuthentication" type="LeastPrivilege.CustomBasicAuthentication.CustomBasicAuthenticationModule, LeastPrivilege.CustomBasicAuthenticationModule, Version=1.0.0.0, Culture=neutral, PublicKeyToken=F20DC168DFD54966"/>
    </modules>

    <security>
        <authentication>
            <customBasicAuthentication enabled="true" realm="TEST" providerName="AspNetWebConfigMembershipProvider" cachingEnabled="true" cachingDuration="15" requireSSL="false"/>
        </authentication>
        <authorization>
            <deny users="?" />
        </authorization>
    </security>
</system.webServer>

<system.web>
    <membership defaultProvider="AspNetWebConfigMembershipProvider">
        <providers>
            <add name="AspNetWebConfigMembershipProvider" type="LeastPrivilege.AspNetSecurity.Samples.WebConfigMembershipProvider, WebConfigMembershipProvider"/>
        </providers>
    </membership>

    <authentication mode="Forms">
        <forms>
            <credentials passwordFormat="Clear">
                <user name="jack" password="jack"/>
                <user name="jill" password="jill"/>
            </credentials>
        </forms>
    </authentication>

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

<location path="Dir1" allowOverride="false">
    <system.web>
        <authorization>
            <!-- <allow users="jack" /> -->
            <deny users="*" />
        </authorization> 
    </system.web>
</location>

<location path="Dir2"  allowOverride="false">
    <system.web>
        <authorization>
            <!-- <allow users="jill" /> -->
            <deny users="*" />
        </authorization> 
    </system.web>
</location>
</configuration>

Best Solution

Update #3

You can enable URLAuthorization to force IIS to protect files that aren't normally processed in IIS. The solution here depends on IIS 7.x and using Integrated pipelines.

<system.webServer>
    <modules>
        <add  name="FormsAuthenticationModule"  type="System.Web.Security.FormsAuthenticationModule" />
        <remove  name="UrlAuthorization" />
        <add  name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule"  />
        <remove  name="DefaultAuthentication" />
        <add  name="DefaultAuthentication"  type="System.Web.Security.DefaultAuthenticationModule" />
    </modules>
</system.webServer>

Updated #2 You can switch entirely to Forms authentication only by removing the custom things you've added and do the following.

I've actually tested this and it only allows jack in to dir1 and jill in dir2. Both can access the root.

If this doesn't work, we'll need to discuss more of your setup.

web.config

<?xml version="1.0"?>
<configuration>
<system.webServer>
    <modules>
        <add  name="FormsAuthenticationModule"  type="System.Web.Security.FormsAuthenticationModule" />
        <remove  name="UrlAuthorization" />
        <add  name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule"  />
        <remove  name="DefaultAuthentication" />
        <add  name="DefaultAuthentication"  type="System.Web.Security.DefaultAuthenticationModule" />
    </modules>
</system.webServer>
    <system.web>
        <authentication mode="Forms">
            <forms loginUrl="Login.aspx" defaultUrl="Default.aspx">
                <credentials passwordFormat="Clear">
                    <user name="jack" password="jack" />
                    <user name="jill" password="jill" />
                </credentials>
            </forms>
        </authentication>
        <authorization>
            <deny users="?"/>
        </authorization>
        <compilation debug="true"></compilation>
        <customErrors mode="Off"/>
    </system.web>
    <location path="dir1">
        <system.web>
            <authorization>
                <allow users="jack" />
                <deny users="*, ?" />
            </authorization>
        </system.web>
    </location>
    <location path="dir2">
        <system.web>
            <authorization>
                <allow users="jill" />
                <deny users="*, ?" />
            </authorization>
        </system.web>
    </location>
</configuration>

Login.aspx - You must add in the redirect from the Login control because otherwise Forms authentication will look for a database in the App_Code directory, which doesn't exist.

<asp:Login ID="Login1" runat="server" OnAuthenticate="Login1_Authenticate">
</asp:Login>

Login.aspx.cs

protected void Login1_Authenticate(object sender, AuthenticateEventArgs e)
    {
        string username = Login1.UserName;
        string password = Login1.Password;
        if (FormsAuthentication.Authenticate(username, password))
        {
            FormsAuthentication.RedirectFromLoginPage(username, false);
        }
    }

Update #1

I went through the example that you linked as Custom Basic Authentication HTTP Module and then followed through to The HTTP Module which has a link at the very bottom to additional source.

This source has a membership provider example using the custom basic authentication. I feel like you're running in to troubles by mixing in the Forms membership provider that you have in your web.config.

When you start to make your own separate authentication, things don't go nicely and you usually need to add in your own everything.

This code works from that additional link on my end.

As an added possibility, if you would like to let ASP.NET handle all of the membership itself and you are using SQL to store everything, consider looking at http://weblogs.asp.net/sukumarraju/archive/2009/10/02/installing-asp-net-membership-services-database-in-sql-server-expreess.aspx to see how to use the wizard to set it up in SQL.

The built in membership will be Forms authentication and be a lot less work than using custom.

Previous Version

I've never had luck with using the <location> tags so I just put new web.configs in the directories. I've also had troubles when I don't exclude anonymous in sub folders as well. This seems to be that the browser will default to anonymous which will get through

Here is how I do it.

Root web.config

<system.web>
    <authorization>
        <allow roles="AccessRole1, AccessRole2" users="domain\jack, domain\jill"/>
        <deny users="*, ?" /> <!-- make sure you deny anonymous with '?' -->
    </authorization>
</system.web>

Sub directory web.config. Make sure you explicitly deny all other users. If you don't deny all other users, they can still get in.

<?xml version="1.0"?>
<configuration>
    <system.web>
        <authorization>
            <allow users="domain\jill" />
            <deny users="*, ?"/> <!-- explicitly deny all others, including anonymous -->
        </authorization>
    </system.web>
</configuration>