Thursday, November 6, 2008

Using SiteMinder authentication in Sharepoint

Introduction
Many enterprise IT environments use Netegrity SiteMinder (hereafter called SiteMinder) to secure Web applications and servers. When customers decide to move to MS SharePoint 2007 (MOSS), they want to continue to use SiteMinder for their existing Web environment, and also as the authentication mechanism for their portal.
This article is an example of the implementation of the solution that allows using the SiteMinder authentication with WSS 3.0.
The key technical points of the solution:
1. SiteMinder authentication.
2. FBA (Form Based Authentications) for SharePoint applications.
3. Custom login form.
4. Custom membership and role providers.

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 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 make the SharePoint framework to authorize (or deny) the authenticated 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 we are going to use the custom authentication mechanism (not Windows authentication) we have to use the Form Based Authentication. Our form shouldn’t have any UI, and 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, the application URL is displayed at the upper-right corner of the page.
When you see the authentication type for your application (it’s 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
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 loginURL to _layouts\logon.aspx. In the modified web.config file of the SharePoint application you will see something like this:

<authentication mode="Forms" > <forms loginUrl="_layouts\login.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 her User Name and Password. It’s not what we want, our 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: looks like 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 decided to use “client software integration” feature.

Custom membership and role providers
Since we are not using Windows authentication we 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. When SharePoint site authorizes users, it uses the list of users and roles assigned to the site. To assign users and roles to the site 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 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 relationship information between users and groups.
By the way, 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 some more complex cases one of possible solutions would be copying the users and roles information in a 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.
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 was not necessary to develop custom providers. The authors of the articles use LDAP membership and role providers that talk to the same data source (AD domain) as the ‘SiteMinder’.
There is another trick both articles are using, instead of changing login.aspx they create HTTP modules that intercept all requests, and create 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 it’s not covered by the article but looks like in both cases the role provider is not used, so the roles are not used for the SharePoint applications.

Followers