Getting Inherited Config Settings

Yesterday, I wrote an HttpModule to support enabling Http basic authentication for Web APIs running in an ASP.NET host.  But wait, you say – IIS already supports basic authentication?!?  This is true…kind of.  Basic authentication is supported, but only if the credentials being sent across in Http basic can be resolved to Windows credentials – which IMHO seems like a scenario where I would just use integrated Windows authentication – but that’s beside the point.  The point is that I want to support the Http basic flow and validate the credentials using my own credential store.  This has been well documented, so I’m not going to repeat all of that detail here, but I do want to tell you about one thing that tripped me up.

Part of my logic reads like this.  “If anonymous access is enabled, then you don’t need to bother processing any further.”  This means that I need to find out whether anonymous access is enabled or disabled.  Now, this isn’t a problem if I’m configuring authentication in my local Web.config, but in my case, I’m setting this on my Web site (custom host) in the IIS management console.

Untitled

When I configure at the site level, the configuration information is added to the applicationHost.config file

 
<location path="basic.test.local">
  <system.webserver>
    <security>
      <authentication>
        <basicauthentication enabled="false" />
        <anonymousauthentication enabled="false" />
      </authentication>
    </security>
  </system.webserver>
</location>

Cool – so I just need to access this information in my HttpModule and figure out if anonymous authentication is turned on – should be simple.  The problem I ran into was that there are multiple ways that look like they should accomplish this task (and one does if you do some other stuff), but only 1 way seems to work they way I expected.

I started out by trying to access config from the current HttpContext

 
var x = currentContext.GetSection( 
  "system.webServer/security/authentication/anonymousAuthentication"); 
anonymousEnabled = (bool)x["enabled"]; 

That didn’t work – it was always null, though it would work if I set the values in my local config file.

So I tried the sledge hammer approach using the IIS admin api

 
using(var serverManager = new ServerManager()) { 
  var config = serverManager.GetApplicationHostConfiguration(); 
  var anonymousSection = config.GetSection( 
    "system.webServer/security/authentication/anonymousAuthentication", 
    "basic.test.local"); 
  anonymousEnabled = (bool)anonymousSection["enabled"]; 
} 

This approach actually did give me the value that I wanted, but there were a couple problems with the approach

  • It required me to give my app domain read permissions to %windir%\system32\inetsvr\config – and that just feels wrong on multiple levels
  • It required me to declare my site name – which seems pretty brittle

What I really wanted was a single API that will project the consolidated configuration information from my local Web.config all the way up to my applicationHost.config – I mean, at the end of the day, IIS needs this information, so certainly it’s exposed somewhere, right?

Yes

 
var y = WebConfigurationManager.GetSection( 
  "system.webServer/security/authentication/anonymousAuthentication"); 
anonymousEnabled = (bool)y["enabled"]; 

If you already knew this, awesome – I wish you had been around to help me.  If you didn’t know this, hope it helps.

About Howard Dierking

I like technology...a lot...
This entry was posted in Web. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Aleks

    Sorry, in fact it was not working.
    This is better :

    protected bool IsAnonymousAllowed
    {
        get
        {
            bool result = false;
            using (ServerManager sm = new ServerManager())
            {
                result = (bool)sm.GetApplicationHostConfiguration().GetSection(“system.webServer/security/authentication/anonymousAuthentication”)["enabled"] // this will look to the server configuration file
                || System.Web.Security.AnonymousIdentificationModule.Enabled; // this will look to local configuration file
            }
            return result;
        }
    }

  • Aleks

    I tried this and it works for me : System.Web.Security.AnonymousIdentificationModule.Enabled

  • http://boxbinary.com Alex Norcliffe

    Hey there Howard, and congrats again on the new arrival (this time in Disqus form!)

    Thought I’d let you know about the DeepConfigManager in Umbraco.Framework in v5, it allows you to do a search on config sections but from the “bottom-up”.

    We use it to allow plugins to override configuration by just having a stub web.config file in their own folder, so config (to all intents and purposes) rolls back when you delete the plugin.

    I also went crazy on the xmldocs :) http://umbraco.codeplex.com/SourceControl/changeset/view/2dc3f2c882f2#Source%2fLibraries%2fUmbraco.Framework%2fConfiguration%2fDeepConfigManager.cs