6
votes

Here is my scenario:

I've got a website set up in IIS (7.5) that uses Forms Authentication. I've got a subfolder within that website that I'm using as a WebDAV share. I've got a custom HTTP Module monitoring my WebDAV requests and also acts as a level of custom authentication. This custom authentication will first send a HTTP 401 Challenge to get the user's credentials when they try to map a drive to my WebDAV share, and then the credentials are parsed out of the Basic-Auth header server-side. The problem is that a Basic-Auth header is only sent if Forms Authentication is turned off.

What's more is that normally when my HTTP Module doesn't find an Auth Header, a 401 Challenge is sent (which prompts the user for credentials when Forms Auth is turned off). However, with Forms Auth turned on, my HTTP Module still executes and sends a 401 Challenge, but it appears that the Forms Auth is taking priority so in Fiddler I can clearly see a redirect to:

/Account/Login.aspx?ReturnURL=MySubFolder

The point of the custom authentication is so that I can allow the user to log-in to my site when mapping a drive to my WebDAV share. I want to capture their website credentials, authenticate them, and then show them the contents of the directory.

So my question is:

Is there a way to get Forms Authentication disabled on a subfolder or Virtual Directory within a website which has Forms Authentication enabled?

I've verified that I can get around this by creating a new Application in my website and put the subfolder in there, and then disable Forms Auth on the Application itself, but I'd really prefer not to do that if possible.

Everything I've tried (listed below) has resulted with my request to map a drive to Http://localhost/MySubFolder getting taken over by Forms Authentication (at least that's what I think is happening) and redirected to /login.aspx?ReturnUrl=MySubFolder (as shown in Fiddler).

Here's what I've tried:

1) Added a separate Web.config in MySubFolder:

   <configuration>
     <system.web>
       <authorization>
         <allow users="*"/>
       </authorization>
     </system.web>
   </configuration>

2) Added a <location> tag in the root-level Web.config for MySubFolder like this:

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

3) Looked at updating the Feature Delegation in IIS.

Personally, I had some doubt with the above solutions because from what I've read, they are meant to simply allow all access while still leaving Forms Authentication enabled. I need a way to actually get Forms Authentication disabled on my subfolder. Is this possible?

I should also note that my subfolder could be a Virtual Directory, but it's not required one way or the other. I just need a way for Forms Auth to be disabled on that folder.

As per request, my Web.config file (site-level):

<?xml version="1.0"?>
<configuration>
  <connectionStrings>
    <add name="MyConnString" connectionString="Persist Security Info=True;Initial Catalog=MyDB;Data Source=MyServer;User ID=UserName;Password=xxxxxxxxxx;MultipleActiveResultSets=True;"/>
  </connectionStrings>
  <system.web>
    <compilation debug="true" strict="false" explicit="true" targetFramework="4.0" />
    <authentication mode="Forms">
      <forms loginUrl="~/Account/Login.aspx" timeout="2880" />
    </authentication>
  </system.web>
  <system.webServer>
    <modules runManagedModulesForWebDavRequests="true" runAllManagedModulesForAllRequests="true">
      <add name="CustomWebDAVModule" type="CustomWebDAVModule"/>
    </modules>
  </system.webServer>
</configuration>
3
Can you post your web.config file. Please take care to obfuscate critical information like db user credentials etc when posting.Tanzeel Kazi
Thanks for the comment, @TanzeelKazi. I've looked into this further, and was able to narrow my question down to be more specific. I've also listed my entire Web.config, which is very minimal in my testing set-up. Please let me know if I can provide any further information!lhan
I couldn't for the life in me figure out why my MVC application was stripping the virtual directory name when forwarding to the login url. Turns out i missed the ~.Stuart

3 Answers

5
votes

This question has already been answered: Multiple/Different authentication settings in web.config

You can't override the root authentication mode="Forms" tag within location tags. Making the folder it's own application is the easiest way out.

Another option is to implement your own custom Forms authentication and have it ignore the redirect for your webdav folder.

<authentication mode="None">
1
votes

Apparently you have not correctly setup WebDAV within IIS.

Since you want to use a custom webdav module for authentication we first need to ensure that IIS does not interfere with your WebDAV requests.

Follow these steps (note that the important point is in step 7):

  1. Keep your web.config as is (as posted in the question).

  2. Enable WebDav within IIS. Within the IIS manager select your website. Within the main window open WebDAV Authoring Rules.

    Open WebDAV Authoring Rules

  3. In the actions pane (on the right) click Enable WebDAV.

    Enable WebDav

  4. Now select your sub-folder that you want to enable WebDAV for (I am using path3 in my example) by clicking it and then open WebDAV Authoring Rules.

    Open WebDAV Authoring Rules for sub-folder

  5. Click Add authoring rule... in the actions pane (on the right).

    Click -Add authoring rule...-

  6. In the dialog that opens make sure all of these are selected All content, All users, Read, Source and Write and click OK. This will grant access to all content of that subfolder to all users with all permissions.

    Add authoring rule

  7. Now the most important part. Since you want to handle WebDAV authentication through your custom WebDAV handler we must explicitly tell IIS not to interfere with authentication. How do we do that? We tell IIS to allow anonymous WebDAV access. This way IIS does not try to authenticate the user and your module is free to do its authorization operations. To go about doing this we will need to set Allow Anonymous Property Queries to True under WebDav settings. The next steps will highlight how to do this.

  8. Open the site root WebDAV Authoring Rules.

    Open WebDAV Authoring Rules

  9. Click WebDAV settings....

    Click -WebDAV settings...-

  10. Set Allow Anonymous Property Queries to True.

    Set Allow Anonymous Property Queries

  11. Close and restart the WebDAV client that you will be testing on. This is to ensure that it does not cache connection parameters from the previous incorrect configuration.

  12. Check to see if the WebDAV configuration of your website works as desired. :)

1
votes

Within your custom HTTP Module, you can tell the Forms Authentication to supress the redirect via HttpResponse.SuppressFormsAuthenticationRedirect:

public class DavAuthenticationModule : IHttpModule
{
        public void Init(HttpApplication application)
        {
            application.AuthenticateRequest += App_OnAuthenticateRequest;
        }

        private void App_OnAuthenticateRequest(object source, EventArgs eventArgs)
        {
            // Only applies for WebDAV requests.
            var ctx = HttpContext.Current;
            if (!ctx.Request.Path.StartsWith("/dav/path", StringComparison.OrdinalIgnoreCase))
                return;

            // So that forms auth won't do a redirect.
            // Note that it will still attempt to read / parse the forms auth cookie.
            ctx.Response.SuppressFormsAuthenticationRedirect = true;        

            // Now do my own auth.
            DoBasicHttpAuthentication(ctx);
        }
}

Another option is to hook the FormsAuthenticationModule.Authenticate event to authenticate before Forms Auth runs at all. This would require you to fish around in IIS for the module instance, which I don't have an example for.

Both these options are based on the .NET 4.6 reference source: http://referencesource.microsoft.com/#System.Web/Security/FormsAuthenticationModule.cs,ac471f8ac73cdb2b