Introduction
Many enterprise IT environments use Netegrity SiteMinder (hereafter called SiteMinder) to secure Web applications and servers. Customers who decide to move to MS SharePoint 2007 (MOSS) want to continue to use SiteMinder for their existing Web environment and as the authentication mechanism for their portal.
This article is an example of how to implement a solution that makes it possible to use the SiteMinder authentication with WSS 3.0.
There are four key technical points to the solution:
1. SiteMinder authentication
2. FBA (Form-based authentications) for SharePoint applications
3. Custom login form
4. Custom membership and role providers
Audience
I assume that you have already got some idea about SharePoint 2007, you know how to use the Central Administration web site.
You know the provider model of .Net 2.0 and how to use providers for in Asp.Net 2.0 for custom authentication and authorization. I also recommend creating a simple membership provider for Asp.Net 2.0 and run it in debugger mode to see how and when it’s called by the .Net framework.
I also recommend reading other blogs about SiteMinder authentication for SharePoint 2007 (see Additional Information at the end of this blog.)
SiteMinder authentication
The SiteMinder authentication is used for single sign-on (SSO) functionality. Once SiteMinder authenticates a user, it adds a special HTTP header with the user name to each HTTP request. SiteMinder can also create an authentication cookie that can be used if you want client software integration, for example, if you want to modify a document from a document library, using MS Word.
Since the SiteMinder authenticates users, the SharePoint authentication can be, and should be, bypassed. we trust that the user is already authenticated and his or her name is contained in the HTTP header. The custom login form pulls the UserID from the HTTP header, creates the authentication token, and redirects the request to the destination page. The trick is to ensure that the SharePoint framework authorizes (or denies) the user correctly. To resolve users and role names the SharePoint framework has to use custom membership and role providers.
FBA (Form-based authentications) and custom login form.
Since you are going to use the custom authentication mechanism (not Windows authentication), you will have to use form-based authentication (FBA). The form shouldn’t have any UI, and the user shouldn’t even be aware that the form is called.
The FBA has to be set up on the SharePoint Central Administration website. After opening the site go to: Application management->application security->authentication providers.
At this point, make sure that you are changing the right SharePoint application. You will see the application URL displayed at the upper-right corner of the page.
When you see the authentication type for your application (iwhich is Windows by default), click “Default,” and you will be navigated to the “Edit authentication” page.
On this page you can set up the form-based authentication and the membership and role providers.
If you want to be able to edit documents from document libraries using MS Office software, don’t forget to click the “client software integration” radio-button on this same page.
After you set up the FBA authentication for a SharePoint application, the central administration web site changes the web.config file of the SharePoint application. It sets up the authentication to “Forms” and sets loginURL to _layoutslogon.aspx. In the modified web.config file of the SharePoint application you will see something like this:
<authentication mode="Forms" >
<forms loginUrl="_layoutslogin.aspx"/>
</authentication>
This setting will cause any unauthenticated request to be redirected to the SharePoint default login.aspx page, and the user will be prompted to type his or her user name and password. This is not really what you want, though. Your purpose is to let the user, authenticated by the SiteMinder, bypass any additional authentication. The login form shouldn’t have any UI. Replace the loginURL attribute with the name of the custom web page (in this example the name of the page is SiteMInder_Login.aspx).
Figure 2 SiteMinder_Login.aspx.cs
public partial class SiteMinder_Login : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string strUserName = GetCurrentUserLoginID(Request);
FormsAuthentication.RedirectFromLoginPage(strUserName, true);
}
public static string GetCurrentUserLoginID(System.Web.HttpRequest Request)
{
string strHeaderName = System.Web.Configuration.WebConfigurationManager.AppSettings["UserIdHeaderName"];
return GetSMAttribute(strHeaderName, Request);
}
public static string GetSMAttribute(string AttrName, System.Web.HttpRequest Request)
{
string AllAttrs = Request.ServerVariables["ALL_HTTP"];
int Location = AllAttrs.IndexOf(AttrName);
string bigResult = AllAttrs.Substring(Location + AttrName.Length + 1);
int N_Location = bigResult.IndexOf(‘n’);
string strResult = bigResult.Substring(0, (N_Location – 1));
return strResult;
}
}
The GetSMAttribute method gets the HTTP header with the user name. For some reason Request.Headers[AttrName] didn’t work for me; it just wouldn’t find the header, so I had to get “ALL_HTTP” server variable string and then parse it.
Another tip: Apparently you don’t get the SiteMinder headers if the session is disabled (it’s disabled by default on SharePoint applications), so you will have to enable the session in the application web.config file.
After the login page pulls the user name from the HTTP header, it redirects the user to the requested page and creates the form authentication token. It also creates the persistent cookie (the second parameter in the method is true). You need the persistent cookie if you are going to use “client software integration” feature (which you will already have selected).
Custom membership and role providers
Since you are not using Windows authentication, you need to define membership and role providers for the SharePoint application and Central Administration site.
After the SiteMinder authenticates a user, the SharePoint framework has to authorize the user. The SharePoint site uses the list of users and roles you have assigned to authorize users,. To do this in SharePoint 2007, you use the Central Administration site (to assign site collection admins) or Site Settings (to assign users and groups). In both cases the SharePoint framework uses the assigned membership and role providers. The framework calls appropriate methods of the providers to search for users and roles. Providers make calls to data sources that contain users, groups, and information about the relationship between users and groups.
Incidentally, SharePoint stores users and groups assigned to sites in the Contents database in the form: ProviderName:UserName.
If your SiteMinder agent authenticates users against a specific AD domain you can use LDAP membership and role providers that will talk to the same AD domain. In more complex cases, one solution would be to copy the users and roles information into an SQL server database and use providers that talk to this database.
Figure 3 The HTTP request sequence diagram
See my blog about custom membership and role providers for SharePoint 2007.
Additional information
There are blogs on the Internet about using the SiteMinder headers to bypass the SharePoint authentication. The following are two examples.
http://www.huffs.us/blog/2007/04/siteminder-and-sharepoint-2007.html
http://blogs.msdn.com/danielma/archive/2005/11/16/493519.aspx
In both cases, the SiteMinder talks to one AD domain, and, because of that, it does not require custom providers. The authors of these articles use LDAP membership and role providers that talk to the same data source (AD domain) as the “SiteMinder”
There is another trick that the authors of both articles are using. Instead of changing login.aspx, they create HTTP modules that intercept all requests ,and create a generic principal object using the user name from the SiteMinder header. In this case login.aspx is never called.
It’s not absolutely obvious, and the authors of the article do not address it, but it looks like the role provider is not used, in either case. This means that the roles are not used for the SharePoint applications.