ASP.NET Security
As a Domino developer, we've been spoilt for quite some time by having easy access to usernames and passwords to authenticate against applications. The Domino directory is easy to use, and the server does most of the integration work for you. It's also easy to extend this, and have external directories made available through Directory Assistance, and also to have applications which act as their own 'Directory' simply by including a few design elements from the main Directory Template.
So when it came to creating some access control for my Project, I didn't really know where to start. It was pretty obvious that Windows authentication was there for me as an option, but it wasn't one I really wanted to take. It linked my application to my development environment in a way which didn't seem right for an application of this size. All of the code snippets that I'd seen about Windows authentication made it pretty clear that it was very handy for enterprise wide applications with many users and roles, and very easy to use if you were developing for an environment that relied heavily on Active Directory, but then on the other hand I'd seen code floating about which made it clear that there were other ways of handling security. I'd often seen code which referenced placing passwords for database access inside aspx files, which made me think there must be some way to provide form level security without needing AD.
..and of course, there is. Funnily enough, it's referred to as Forms Authentication.
The Basics of Forms Authentication
There's plenty of info on this stuff floating around the web. What I'll describe is why you might want to use this method of authentication, and make some comparisons which will hopefully be of use to you as a Domino developer.
For my application, I really only have 2 classes of user. I have the Admin user, and then everyone else. This makes things pretty simplistic from an access control perspective, and makes it pretty easy to see why I didn't really want to use active directory. Forms authentication is perfect for my application, because as well as my simplistic user model, I'm only really going to have a couple of forms which are restricted. I'll be needing a data entry form to add content to the database, and possibly some form of comments admin form to let me delete rouge comments, although if I wanted to skip functionality then the latter is something that could easily be handled by the SQL Server enterprise manager client. Every other form will simply be reading data from the database, and open to everyone.
Forms based authentication is managed via the web.config. A sample looks something like this:
It's pretty basic, and possibly not quite as elegant as using the Domino directory, but for simple applications it'll do quite nicely. There are additional security options, which I'll talk about in a second. Now that we've defined some users, we want to protect a few things. We have a line in there which allows all users access to everything, so now we need to add some exclusions for the things we want to protect. This is done pretty easily, by adding some location definitions:
In the above examples you'll see * and ? - * denotes "All authenticated users", and ? denotes "All anonymous entries", which are concepts any Domino developer should be pretty used to. Other than that, you can state who is allowed and who is denied to these resources, it's as simple as that.
The login form
In the first image theres a loginURL thats defined for the application. It's purpose is pretty obvious. Here is a sample login.aspx which should show you everything you need to know. The concept is similar to what we'd store in our domcfg.nsf database, however there's a little bit of code in there which handles the authentication for us. This is what we'd need to change if we wanted to extend our login so it referenced a proper user database. Basically ASP.NET requires us to define this login form at a per application level, which is fine.
Here's a bit more info about a couple of the functions used when the user clicks login;
FormsAuthentication.Authenticate
The single login button on the webpage calls the Login_Click method when clicked. In this method, we use the FormsAuthentication.Authenticate(username,password) to get ASP.NET to check the credentials of the user. The parameters for this method is pretty straightforward and it just returns a boolean value.
FormsAuthentication.RedirectFromLoginPage
If the user is providing proper credentials, then we'll use the FormsAuthentication.RedirectFromLoginPage method. The parameters of this method are a username string and a boolean value. The first parameter is a username string and it is a name of the user for cookie authentication purposes. The value you put in there will be the user name that the client is associated with. It does not need to match the username used in the FormsAuthentication.Authenticate method but it is advisable to set the cookie to the username that was used to log in. The second parameter is a boolean value and it specifies whether or not a durable cookie (one that is saved across browser sessions) should be issued.
If you remember, when a user requests a page without proper authentication, they are redirected to the login page. After setting the cookie, the RedirectFromLoginPage will then send the user back to the page they came from.
Further security
Anyone with a wee bit of security knowledge would look at the plaintext passwords in web.config and be kind of horrified. Fortunately web.config supports SAH1 or MD5 hashed passwords. You need to hash them yourself, and change the passwordFormat in order to do so. The next step up is to store the passwords in another area, such as a database or in a seperate file. Again, there's plenty of samples out there explaining how to do this if you want to take your security further.
Summary
Domino Developers have been spoilt a little bit when it comes to authenticated applications. The Domino directory is easily accessible and the Domino server has always done a lot of the work around authentication for you. However things in ASP.NET aren't too bad by comparison. Simple applications can use a web.config to define users, and this can easily be extended to reference an xml file, a database, or finally active directory for large enterprise wide applications. The best thing about the web.config approach is that it provides a quick and easy starting point for anyone who wants to play about with some simple form based web authentication tests without requiring any large amount of infrastructure.