11

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>
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
Philipp Grathwohl
  • 2,726
  • 3
  • 27
  • 38

5 Answers5

10

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>
Kirk
  • 16,182
  • 20
  • 80
  • 112
  • I don't have roles or domainusers. I tried to exclude the anonymous users as well, but I still have the same problem. I think the problem may be somewhere with the custom MembershipProvider and/or CustomAuthentication. – Philipp Grathwohl May 02 '12 at 09:36
  • Can you provide the details of your membership / authentication code? I've created a couple simple ones in the past and may be of some help. – Kirk May 02 '12 at 16:23
  • As mentioned in the question, I used the MembershipProvider from here: http://www.leastprivilege.com/PermaLink.aspx?guid=628c9d74-9039-4465-8533-e821506aa9a2 with the extension http://www.leastprivilege.com/ASPNETMembershipProviderForWebconfig2ndTry.aspx in combination with the HTTP Module. Please let me know what information you need. Thanks – Philipp Grathwohl May 02 '12 at 16:45
  • Oops, I missed that. I'll try to go over it a bit and see if I can see what's going on – Kirk May 02 '12 at 16:57
  • I used the MembershipProvider (Forms) so I can define the users in the web.config instead of a SQL Database. But in this case I'll try that. Do you know any other MembershipProvider that lets me define users in the web.config? – Philipp Grathwohl May 02 '12 at 18:35
  • You may be able to stick with Forms authentication like you were and remove the custom code. Take a look at . I'll update my answer with an example of that too. – Kirk May 02 '12 at 18:57
  • Thank you very much for your effort. I can not switch to Forms authentication because some of the files are downloaded automatically by clients that expect basic authentication. Does the url-authentication work independently from the forms authentication (but with the specified credentials in the web.config), then I think it would be acceptable. – Philipp Grathwohl May 02 '12 at 20:12
  • You can try adding in the `system.webServer` part and see if it enforces url authorization for basic authentication, I've never used it in that situation. It also needs to be IIS 7.x with integrated pipelines. – Kirk May 02 '12 at 20:19
  • I added the `system.webServer` part to my web.config and changed the `authenticationMode` to `None` so the login.aspx is not required anymore and I can use the basic authentication instead. Seems like the problem was the missing `UrlAuthorization` Module. Please update your answer (once more ;) ) so I can give you the bounty and accepted answer! Thanks a lot! – Philipp Grathwohl May 03 '12 at 07:28
  • Okay. I've added another update, haha. Let me know if I explained it properly for you to accept it. – Kirk May 03 '12 at 15:00
2

Here is a link to a good article with details to several situations, where one would want to allow/deny access to particular page or folder:

Setting authorization rules for a particular page or folder in web.config

As a side comment, in one project we do, we use the option of individual web.config file in each folder, as stated in the link as well, and it works for us just fine.

Hopefully, it helps to solve your problem.

utsikko
  • 1,545
  • 1
  • 16
  • 27
  • Thank you for your answer. I added seperate web.config files for the subdirectories like you said. But problem is the same. Every user can still access every subdirectory. – Philipp Grathwohl Apr 03 '12 at 11:13
0

this approach is similar but different - location is a file instead of a directory:

Is it possible to allow anonymous user to browse only few files from a folder

Community
  • 1
  • 1
wazz
  • 4,953
  • 5
  • 20
  • 34
0

Use this step-by-step guide to apply the tag to the Web.config file to configure access to a specific file and folder.

<location path="default1.aspx">
    <system.web>
        <authorization>
            <allow users ="*" />
        </authorization>
    </system.web>
</location>
<!-- This section gives the unauthenticated user access to all of the files that are stored in the Subdir1 folder.  -->
<location path="subdir1">
    <system.web>
        <authorization>
            <allow users="Admin" />
        </authorization>
    </system.web>
</location>

More info...

Majid Hosseini
  • 1,098
  • 10
  • 17
0

Set the following in your Web.config

<modules runAllManagedModulesForAllRequests="false">

Place the following event in your Global.asax file.

protected void Application_BeginRequest(Object sender, EventArgs e)
{
}

Now whenever you type the URl like below.

http://localhost/dir1/jack.txt

The control will always move to Application_BeginRequest event. You have Request.Url information and Current User information and you can do the validation here.

Using below code

throw new HttpException(403,"Acess Denied");

or send the user to some another page with some user friendly message.

Pankaj
  • 9,749
  • 32
  • 139
  • 283