Friday, February 22, 2008

Apache-Style Web Application Security (Almost) in ASP.NET with Web.config

I say "almost" because if it really was Apache-style, it would be easy. But this is Windows we're talking about, so it isn't.

What I wanted to do was pretty simple: launch a web app with anonymous access except for one directory to contain administrative controls, which I wanted to protect with the standard Login control and values stored in Web.config file.

For the Web.config settings, what I saw was all over the map in terms of what goes where, when, and why. Here's what I ended up using:

<configuration>
<!-- ... -->
<system.web>
<authentication mode="Forms">
<!-- When authentication is triggered, the login page will
be /EditLogin.aspx and the user will be sent to
/edit/default.aspx after a successful login attempt. -->
<forms loginUrl="EditLogin.aspx" defaultUrl="edit/default.aspx"
protection="Encryption">
<!-- Putting this into Web.config isn't exactly a security
best practice, but at least we'll use SHA1 encryption. -->
<credentials passwordFormat="SHA1">
<user name="user1" password="AAAAAAAAAAAAAAAAAAAAAAAAAAAA"/>
<user name="user2" password="BBBBBBBBBBBBBBBBBBBBBBBBBBBBB"/>
</credentials>
</forms>
</authentication>
<authorization>
<!-- This says that all users can get access to the app. -->
<allow users="*" />
</authorization>
</system.web>
<!--...-->
<!-- Anonymous access will be true for all directories except
this /edit directory. user1 and user2 can get access, but
all others will be denied. -->
<location allowOverride="false" path="edit">
<system.web>
<authorization>
<allow users="user1, user2"/>
<deny users="?"/>
</authorization>
</system.web>
</location>
</configuration>

Some documentation claims you can use ~/ in the loginUrl and defaultUrl and path definitions. Whenever I included it, the authentication settings were ignored. There are articles out there that start or end their path definitions with a /. This always threw a compile error for me. There are also articles that state you can nest an <authentication> element within <location>/<system.web>, but I always got a compile error on that, too.

I added a Login control to EditLogin.aspx, but I was initially under the impression that on submit the Web.config values would be used and the user would be redirected. This was incorrect. You need to set the Authenticate event handler in your login page.

protected void Login1_Authenticate(object sender,
AuthenticateEventArgs e)
{
if (FormsAuthentication.Authenticate(Login1.UserName,
Login1.Password))
FormsAuthentication.RedirectFromLoginPage(Login1.UserName,
false);
}
You'll also need to add OnAuthenticate="Login1_Authenticate" to the Login control.

I may have missed something obvious where I ran into errors, but I hope this prevents someone else from wasting a few hours of their day!

No comments: