One of the greatest leaps that SharePoint 2003 has made to its 2007 release is the fact it is now built entirely on top on ASP.NET 2.0. SharePoint can now even be thought of as an actual web application, just like any other. While 2003 hacked its way into IIS and ASP.NET, 2007 integrates nicely into its environment, dotting all the I's and crossing all the T's along the way.
Therefore, all the components that we use every day in our web apps should be able to seamlessly play similar roles in SharePoint. This includes web user controls, master pages, managed code, and, as this article discusses, authentication providers. These modules were painful (if even possible) to implement in 2003 and behave much more nicely in 2007. So if you ever find yourself frustrated with the development of some SharePoint functionality, just remind yourself: "Hey, this is just a web app I'm dealing with..."
Before we get started, there are two assumptions/assertions that I'd like to make. The first one is technical, and the second more philosophical. Assumption one is that any code we write is going to be deployed in the global assembly cache (GAC). While this may raise an eyebrow or two among administrators, I will always persist that it is safe, and solves a lot more problems than it raises. There are two crucial SharePoint advantages for this deployment paradigm:
The second assertion is on the behalf of our users. As far as they are concerned, authentication and authorization are all handled by two textboxes (one with letters and one with dots) and button that has the word "Login" on it. They don't care if they are logging into a Windows authentication popup box, typing their password directly into a web page, or dealing with some other mechanism. They want to type their username in one place, their password directly below it, and, if they choose, have the option to never be bothered with this nonsense again.
So in other words, the assertion is that the actual login mechanism is arbitrary. We don't need to be tied down to one authorization paradigm, and be forced to make the entire portal and even the server topology coincide with it. We should be free to build our site around what our users want, and simply make the authentication fit into it. And most importantly, authentication, when customized, can, in the very worst case, be as painful as it is now for our users.
We have a collaboration SharePoint portal for our projects that is shared by both our clients, and our developers, project managers, architects, and sales reps who are creating the solution. So how do we authenticate - and more importantly, authorize - these users? Well, in our 2003 environment, we settled on ADFS and running SharePoint in account creation mode...which worked...but didn't really give us all the control we needed.
So in 2007, we want to create a provider to take care of everything in this regard automatically. Our employees all already have AD accounts, and there is no reason not to leverage our domain controller. So that's easy: employees will be using Windows Integrated Authentication, and be authorized via their AD groups. And what of our clients? Well, we don't want to keep managing ADFS, and we don't want to have to create AD accounts for external users. So the answer comes to us straight from ASP.NET 2.0: the Login web user control, the AspNetSqlMembershipProvider database, and Forms-Based Authentication.
So now the real problem is clear: how do we implement two authentication providers at the same time? All of the research I've done in this area has led down dark and scary paths, all of which end up satisfying only a portion of our requirements...and all without even throwing SharePoint into the mix! So instead of a massive IIS hack or a messy AD-to-SQL replication solution, I decided (for a change) to pursue a more elegant solution: make one provider do the work of both.
Now, which one to chose? Since I only find myself wandering around IIS when I've broken something, (and if I haven't alluded to it enough already) we are going to go down the forms auth road. Personally, I will always prefer to code rather than to configure. However, if you don't, I can't foresee any reason why this technique can't be "reversed" to work with Windows auth. I haven't tested this, but feel free to go in this direction if your strengths are more in this area.
The solution to this problem comes in three pieces: first, we'll write some code; second comes deployment; and finally everything gets wired up. We'll be needing Visual Studio and a web farm containing a SharePoint 2007 instance, a domain controller with AD, and a SQL Server database. For development purposes, these can all be living on the same physical box or virtual machine. Finally, the SharePoint portal will have at least two web applications - one for the Central Administration site, and one for the Portal Site.
Let's start with the code for phase one.
The second phase is deployment. I like to create a folder called something like "SharePoint" off the root on the server's hard drive to act as a staging area for assemblies, components, updates, documentation, and other files that pertain to my portal. The only files that go into web application's folders should be content-related: web user controls, ASPX pages, style sheets, etc.
Note: this can really go anywhere beneath this folder, or in the "global" layouts folder in C:\program files\common files\microsoft shared\web server extensions\12\template\layouts, but I prefer to have my portal content explicitly in my web application's folder, because that coincides more with how an ASP.NET web app works.
Next, we need to "deploy" the database. We'll use the ASP.NET SQL Server Setup Wizard to first create the standard database with all the tables and stored procedures that that ASP.NET SQL Membership Provider is already wired up to use. Then we only need to create a user that has full access to this database to reference in our connection string.
Finally, it's time to roll up our sleeves and wire everything together. The last phase, configuration, can be the most tedious because we'll be updating web.configs, making settings changes in Central Admin, and generally doing things that, when not done correctly, can crash the entire portal. Note: if you already have a provider in place and existing users and groups, changing the provider will invalidate those users (since, "provider1:username," for example, is technically different than " provider2:username").
Now, we can go into the Central Admin and "point" SharePoint to our provider. There are three main tasks to take care of: enable forms auth on our web app, set our provider as the membership data source, and finally designate users to be the primary and secondary site collection administrators for our site.
Last task: we need to configure our site's web app to be able to authenticate users from our membership provider.
Visit my CodePlex Project for the latest version of the code.
And there you have it! This method uses forms authentication on a SharePoint web application to authenticate users against both SQL Server and Active Directory. Not only will this hybrid provider be able to manage users across the two most prevalent user data stores in Windows, but it can also be scaled out to support other .NET membership providers, as well as run custom code to query into any source of user information.
Remember, SharePoint 2007 is an ASP.NET 2.0 web application. Any troubles your have along the way of creating and deploying a portal with this technology can be dealt with - and overcome - by applying the standard techniques that you'd normally use to go after any other ASP.NET issue you've encountered before. Have fun!