Identity and Access Strategies for SharePoint Products and Technologies (Part 1): Membership and Provider Architecture

Summary: Explore the membership and role provider architecture and how it operates in Microsoft Office SharePoint Server 2007 and Windows SharePoint Services 3.0. This article is part 1 of 2. (12 printed pages)

Ethan Wilansky, FTI Consulting

Tomek Stojecki, Annapolis Computing

June 2009

Applies to: Microsoft Office SharePoint Server 2007, Windows SharePoint Services 3.0

Contents

  • Introduction to Identity and Access Strategies for SharePoint Products and Technologies

  • Why Use Multiple Identity Repositories in SharePoint Products and Technologies?

  • Membership and Role Provider Architecture in SharePoint Products and Technologies

  • SharePoint Server and the Membership and Role Provider

  • Programmatically Viewing the Provider Architecture in SharePoint Products and Technologies

  • Managing Membership and Role Provider Identity Names in SharePoint Server or Windows SharePoint Services

  • About the Authors

  • Additional Resources

Download the code sample (STSADMCommandsSample) that accompanies this article: Identity and Access Strategies Code Sample for SharePoint Products and Technologies

Read part 2: Identity and Access Strategies for SharePoint Products and Technologies (Part 2): Membership and Role Provider Assignment

Introduction to Identity and Access Strategies for SharePoint Products and Technologies

Tomes have been written about the Microsoft ASP.NET provider architecture, and much of that content focuses specifically on the membership and role providers. In addition, there are probably two dozen blogs about how to configure membership and role providers in Microsoft SharePoint Products and Technologies (which includes Microsoft Office SharePoint Server 2007 and Windows SharePoint Services 3.0). This article provides a variety of links to many of these additional resources. Why, then, write this article? We aim to start where most of these resources stop. Sure, certain items addressed in this article repeat existing guidance to establish context. However, this article delves deeply into describing exactly how SharePoint Products and Technologies use the membership and role providers. Then, it demonstrates how to automatically configure providers into Office SharePoint Server so that SharePoint Server manages the configuration settings for you. The article's examples focus on the Microsoft SQL Server Membership and Role providers and the Lightweight Directory Access Protocol (LDAP) membership and role providers in SharePoint Server 2007, and then briefly explores the Active Directory Federation Services (ADFS) single sign-on (SSO) Membership and Role providers.

Why Use Multiple Identity Repositories in SharePoint Products and Technologies?

Providing access to an organization's internal, secured data is straightforward for employees or contractors in an organization. In this article, we refer to this type of user as an internal user. However, it becomes more difficult when someone who is not directly affiliated through an employment relationship, referred to in this article as an external user, needs access to the same data or a subset of that data. Obviously, authenticating to a system containing secured data requires that each user provide some form of credentials. It is a best practice to keep credentials for external users separated from those for internal users. In general, you can accomplish this in two ways: by maintaining a separate identity repository for external users or by taking advantage of existing external user accounts that are maintained by another company's identity repository.

Using another company's identity repository is referred to as "creating a federated identity relationship." In essence, your company trusts the other company's identity repository and its maintenance of that repository. In contrast, when you maintain user accounts for external users, you are not creating a federated relationship. The external user must log on with a unique set of credentials that you maintain.

There are many reasons why you might want to create these types of relationships. For example, if you host a secure Internet site (a SharePoint site or pure Microsoft ASP.NET custom Web application), you can provide external user access to the site by using a membership and role provider and your own identity repository. If you have a secure extranet site that you must share with another business, you can provide external user access to the site through a federated relationship and a membership and role provider that supports federation to the identity repository of the other business.

Membership and Role Provider Architecture in SharePoint Products and Technologies

Whether or not you create a relationship that is federated, Windows SharePoint Services 3.0 makes it easy to support both models by using the ASP.NET membership and role provider model. Before describing how Windows SharePoint Services takes advantage of the provider model, it is useful to take a closer look at the current providers Microsoft offers. The Microsoft patterns & practices group (Microsoft patterns & practices Developer Center) released a series of white papers (see Additional Resources) that are well worth reading to better understand how these two provider types interact with an identity repository. These papers focus on how SqlMembershipProvider and SqlRoleProvider work with Microsoft SQL Server. They include the source code so that you can watch this interaction for yourself by using the Microsoft Visual Studio debugger. This is explored later in this article, and you can find links to more content in Additional Resources.

After you understand the role and membership provider architectures, an important next step is to survey the available membership and role providers and what identity repositories they support. Table 1 lists the most common providers Microsoft includes with ASP.NET, Active Directory Federation Services (AD FS), and SharePoint Products and Technologies.

Table 1. Microsoft membership and role providers and their use

Role and Membership Provider Used In Provided In

SqlMembershipProvider

SqlRoleProvider

SQL Server

ASP.NET 2.0

AuthorizationStoreRoleProvider

Windows Authorization Manager (AzMan), which allows mapping custom roles to groups or roles in back-end repositories, such as the Active Directory directory service, Active Directory Application Mode (ADAM)/Active Directory Lightweight Directory Services (AD LDS), and AD FS.

ASP.NET 2.0

WindowsTokenRoleProvider

Windows authentication system. Referred to by its key name in machine.config as AspNetWindowsTokenProvider. This name is used when configuring the SharePoint Central Administration default role.

ASP.NET 2.0

ActiveDirectoryMembershipProvider

Active Directory

ASP.NET 2.0

SingleSignOnMembershipProvider2

SingleSignOnRoleProvider2

AD FS

AD FS

LDAPMembershipProvider

LDAPRoleProvider

Accessing LDAP directories via System.DirectoryServices and native LDAP methods (wldap32.dll)

SharePoint Server

In addition, third parties and the open source community have created providers. For examples, see Membership and Role Providers For MySQL, and the XML CodePlex projects ASP.NET XmlProviders and ASP.NET XmlProvider Library. Another interesting membership provider implementation announced on the Microsoft SharePoint team blog is the Windows Live Authentication (WLA) provider to support Windows Live ID in Office SharePoint Server. This is part of the Community Kit for SharePoint (CKS) and is referred to as the CKS:WLA provider.

Although it is not difficult to write your own custom membership and role provider, Microsoft includes support for most common identity repositories. SharePoint Server 2007 extends that capability by including built-in LDAPMembershipProvider and LDAPRoleProvider classes in the Microsoft.Office.Server.Security namespace (part of the Microsoft.Office.Server assembly). As its name suggests, this provider enables you to connect to any identity repository via LDAP. These providers use classes in the System.DirectoryServices namespace and a few LDAP native methods to make these calls. System.DirectoryServices sits on top of Active Directory Service Interfaces (ADSI). This is not ideal because ADSI is a suite of COM interfaces and, with the release of Microsoft .NET Framework 2.0, there is a better managed code namespace for these types of calls: System.DirectoryServices.Protocols. However, instead of creating your own set of providers, in most cases these LDAP providers perform well and are worth using.

Using LDAP native methods appears to handle compatibility issues associated with using ADSI with some non–Microsoft LDAP repositories. Hopefully, Microsoft will release updated LDAP providers that implement System.DirectoryServices.Protocols instead of System.DirectoryServices. The Microsoft Directory Service team designed System.DirectoryServices.Protocols to work with any LDAP-compliant directory. For information about System.DirectoryServices.Protocols, see Introduction to System.DirectoryServices.Protocols (S.DS.P).

SharePoint Server and the Membership and Role Provider

By default, SharePoint Server relies on the built-in authentication and authorization mechanisms provided by Windows authentication (Kerberos, NTLM, Basic, or Digest authentication) through Internet Information Services (IIS).

Supporting the ASP.NET membership and role providers in SharePoint Server involves modifying the web.config file in SharePoint Web applications and adjusting some settings within SharePoint Central Administration or from the Stsadm.exe command-line tool. In "Where Do the Providers Belong" in Identity and Access Strategies for SharePoint Products and Technologies (Part 2): Membership and Role Provider Assignment, we address how to properly configure these settings and then provide an approach for automating this entire process.

Programmatically Viewing the Provider Architecture in SharePoint Products and Technologies

You can use the SPIisSettings class to obtain the names of the default membership and role providers for each Web application's zone. Each SPSite object in Windows SharePoint Services 3.0 and SharePoint Server 2007 can hold multiple settings, depending on the number of zones configured for each Web application. Windows SharePoint Services 3.0 and SharePoint Server 2007 store the information in a generic dictionary, where the SPUrlZone object in SPSite identifies the zone from which the settings are retrieved. Code listing 1 presents a simple Stsadm.exe extension that uses the SPIisSettings class to inspect the specified Web application. The Stsadm.exe extension does the following:

  1. Declares a class that implements the ISPStsadmCommand interface.

    This inheritance allows you to register the class with the SharePoint Stsadm.exe command-line command. For more information about extending Stsadm, see How to: Extend the STSADM Utility in the Windows SharePoint Services 3.0 SDK.

    The main entry point for Stsadm is the Run method.

    Passes the command parameters, as entered by the user, into the Run method in the form of key/value pairs (StringDictionary type in the code). A return value of zero (0) signals a successful operation.

  2. Gets the URL and, optionally, the zone for the target Web application. Then, uses this information to get an SPSite object.

    The CommandHelper class is a simple class written to enable the code to retrieve values of the mandatory and optional command arguments.

  3. Following SharePoint best practices, wraps the SPSite object in a Using statement so that the object is disposed when the call completes.

  4. Within the Using block, gets the SPWebApplication object and, from that, retrieves the IisSettings property for the specified zone by passing in an SPUrlZone object.

    If no zone is specified, passes in the default zone, as shown in the GetZone method.

  5. Displays information about the Web application and zone, and then displays the assigned membership and role provider.

Code listing 1. Stsadm extension code for viewing Web application settings

public class WebAppProviders : ISPStsadmCommand
{        
    /// <summary>
    /// Runs a custom command. 
    /// Runtime exceptions are streamed out to the console window.
    /// </summary>
    /// <param name="command">Command name</param>
    /// <param name="keyValues">Command parameters</param>
    /// <param name="output">Command output</param>
    /// <returns>0 indicates successful command execution</returns>
    public int Run(string command, StringDictionary keyValues, out string output)
    {
        output = String.Empty;

        Uri uri = new Uri(
            CommandHelper.GetArgumentValue(keyValues, "url", true));
        SPUrlZone zone = GetZone(
            CommandHelper.GetArgumentValue(keyValues, "zone", false));
                    
        using (SPSite site = new SPSite(uri.AbsoluteUri))
        {
            SPWebApplication webApplication = site.WebApplication;
            SPIisSettings iis = webApplication.IisSettings[zone];

            output += String.Format(
                "Web App Name: {0}\n", webApplication.Name);
            output += String.Format(
                "Number of zones: {0}\n", webApplication.IisSettings.Count);
            output += String.Format(
                "Requested zone: {0}\n", zone);
            output += String.Format(
                "Membership Provider: {0}\n", iis.MembershipProvider);
            output += String.Format(
                "Role Provider: {0}", iis.RoleManager);
        }

        return 0;
    }

    /// <summary>
    /// Defines a help message for the command.
    /// </summary>
    /// <param name="command">Requested command</param>
    /// <returns>Command help text</returns>
    public string GetHelpMessage(string command)
    {
        string helpText = 
            "-url <full url of a web app in SharePoint>";
        helpText += 
            "\n\t-zone <web app zone, defaults to SPUrlZone.Default>";

        return helpText;
    }
    
    private SPUrlZone GetZone(string zoneArg)
    {
        if (String.IsNullOrEmpty(zoneArg))
            return SPUrlZone.Default;

        switch (zoneArg.ToLower())
        {
            case "intranet":
                return SPUrlZone.Intranet;
            case "internet":
                return SPUrlZone.Internet;
            case "extranet":
                return SPUrlZone.Extranet;
            case "custom":
                return SPUrlZone.Custom;
            default:
                return SPUrlZone.Default;
        }
    }
}

The source code Commands in the code sample Identity and Access Strategies Code Sample for SharePoint Products and Technologies) that accompanies this article (Identity and Access Strategies Code Sample for SharePoint Products and Technologies) contains the Visual Studio 2008 solution, with a deployment project that runs a post-build event that uses wspbuilder. This open-source tool simplifies the process of creating SharePoint solution packages (.wsp files). For more information about the wspbuilder documentation and binaries, see WSPBuilder (SharePoint WSP tool).This post-build event was tested by using both version 0.9.8.0206 and version 0.9.8.0109 of wspbuilder.exe. To ensure a successful build, choose one of these versions of wspbuilder. After expanding the wspbuilder compressed (.zip) file into a folder, add that folder to your search path and then build the solution. If you opened Visual Studio 2008 before adding wspbuilder to your search path, close the IDE and then reopen it before you attempt to build the solution.

After you build the solution, install and run the Stsadm extension as follows.

To install and run the Stsadm extension

  1. Create a folder on your SharePoint instance.

  2. Copy the MsdnOnline.STSADM.Commands.wsp file from the WSP folder in the solution to the folder that you created.

  3. Copy the two batch files at the root of the Command project (deploywithstsadm.bat and upgradewithstsadm.bat) to the same folder that you created in step 1.

  4. From the SharePoint instance, run deploywithstsadm.bat to deploy the solution to your Web farm.

    This batch file retracts and deletes the solution if you deployed it previously, and then it reverses these steps to add and deploy the solution to the SharePoint farm.

  5. To see the new operation added to Stsadm, go to the command line of your SharePoint instance and type the following:

    stsadm -help

    In the list of operations, you can see the webappproviders operation.

  6. To see the parameters that the webappproviders operation takes, type the following:

    stsadm -help webappproviders

    Notice that the two parameters this command takes are -url and -zone.

  7. If you had a Web application named https://www.contoso.com in the Internet zone, type the following to display the provider registered for the Internet zone:

    stsadm -o webappproviders -url https://www.contoso.com -zone internet

How SharePoint Server and Windows SharePoint Services Use the Membership and Role Providers

Thanks to the release of the ASP.NET Providers source code, you can now run the Visual Studio debugger against the Microsoft code while browsing a SharePoint site. This gives you excellent insight into exactly how SharePoint Server or Windows SharePoint Services uses these methods. This information enables you to know what to do if you encounter problems with provider configuration, want to understand how these providers interact with SharePoint Server or Windows SharePoint Services, or decide to build your own providers.

Of the twelve public methods defined for the Membership base class, SharePoint Server and Windows SharePoint Services use the following five public methods:

  • ValidateUser

  • GetUser

  • GetUserNameByEmail

  • FindUsersByEmail

  • FindUsersByName

Note

The profile provider uses the GetUsers method of the membership provider to return all users during a profile import operation.

Of the ten public methods defined for the RoleProvider base class, SharePoint Server and Windows SharePoint Services use the following two methods:

  • GetRolesForUser

  • RoleExists

The membership and role providers are critical during authentication, authorization, and identity searches within the SharePoint interface. The following sections review each of these activities and examine exactly how these providers interact with SharePoint Server or Windows SharePoint Services.

Authentication

Forms authentication in SharePoint Server and Windows SharePoint Services is the same as in any ASP.NET application that relies on the Membership or Role provider architecture.

When a user enters his or her credentials in the SharePoint forms authentication logon screen and then clicks the Sign In button, SharePoint Server or Windows SharePoint Services calls the ValidateUser method. This method uses code specific to the identity repository to verify that the user exists and is capable of authenticating to SharePoint Server or Windows SharePoint Services. This, in turn, assigns the HttpContext.User property to a new GenericPrincipal object.

If you enable the Role Manager in web.config, the RoleManagerModule (HTTPModule) assigns a RolePrincipal object to the user object, which overwrites the previously created GenericPrincipal object. This step is necessary to tie the IsInRole method of the IPrincipal interface to the Role Provider API. The real value of this becomes clear when you want to assign users to roles and then assign those roles to SharePoint groups, instead of assigning individual users to SharePoint groups.

Authorization

SharePoint Server and Windows SharePoint Services manage user authorization via SharePoint groups and SharePoint roles. This is true whether or not you use the ASP.NET provider model. If you enable the Role Manger, a bit of extra processing occurs. As an authenticated user navigates SharePoint Server or Windows SharePoint Services, the IsInRole method of the RolePrincipal object calls the GetRolesForUser method of the Role Provider. This method returns a string array containing all of the roles of which the user is a member. SharePoint Server or Windows SharePoint Services uses this information to verify that the user is a member of a role that is authorized to access the target location.

Searching for Users

SharePoint Server and Windows SharePoint Services contain the PeopleEditor control (referred to as the People Picker in the user interface), which you use to search for users and roles or groups defined outside of SharePoint Server or Windows SharePoint Services (see Figure 1). For example, when connected to Active Directory, the People Picker displays Active Directory users and groups. Within a Web application, you use this control to assign people and groups to SharePoint roles or to assign individual SharePoint permissions for a resource.

Figure 1. Simplified anatomy of the People Picker

Simplified anatomy of the People Picker

When you click the Resolve button (Figure 1) of the People Picker in a Web application that uses a custom provider configuration, SharePoint Server or Windows SharePoint Services calls the GetUser method of the membership provider to resolve the specified account.

Searching for a Specific User

If you click the Browse button (Figure 1) to display the Select People and Groups dialog box (PickerDialog control) and then enter a valid user name, SharePoint Server or Windows SharePoint Services also calls the GetUser method. This call returns a MembershipUser object. When this object gets returned, SharePoint Server or Windows SharePoint Services then calls the FindUsersByName method and then the FindUsersByEmail method. The reason for the two sets of calls is to return both specific users and users that are a match by using a wildcard search.

Note

For this process to work, you must include the wildcard character in web.config, as described in the next section, Implicitly Searching by Using a Wildcard. Ultimately, SharePoint Server or Windows SharePoint Services returns a MembershipUserCollection object that is used to display properties in the main window of the PickerDialog control (Figure 1).

Explicitly Searching by Using a Wildcard

If you enter part of a user name in the PickerDialog control, and you have configured the wildcard character in web.config and have not scoped the people picker to a site collection, then the GetUser method does not return a MembershipUser object. Instead, SharePoint Server or Windows SharePoint Services makes the following series of method calls:

  1. Calls GetUserNameByEmail, which returns null unless you entered a specific e-mail address.

    The input name to this method does not contain the configured wildcard.

  2. Calls FindUsersByEmail to return a MembershipUserCollection object.

    SharePoint Server or Windows SharePoint Services takes the input name exactly as you entered it and attempts to resolve the account by using several methods, including FindUsersByEmail. This specific call to FindUsersByEmail will not return a value from the identity repository unless there is an exact match on the e-mail address. However, SharePoint Server or Windows SharePoint Services might find a match within the SharePoint site collection. Any matches are appended to the result set.

  3. Calls FindUsersByName to return a MembershipUserCollection for all matching user names in the identity store.

    In this case, SharePoint Server or Windows SharePoint Services appends the input name with the wildcard character specified in web.config for the membership provider. Any wildcard matches on the user name from the identity repository are appended to the result set.

  4. Calls FindUsersByEmail again to finally return a result set that contains a collection of users with matching e-mail addresses.

    Like the FindUsersByName method, SharePoint Server or Windows SharePoint Services appends the input name with the wildcard character. Any wildcard matches on the e-mail address from the identity repository are merged into the result set.

A special case scenario that can be confusing is when you enter part of a user name, but do not use the wildcard matching character for the target identity repository and do not enable wildcard search in web.config. Although this does represent an improper or incomplete configuration of the membership provider in SharePoint Server or Windows SharePoint Services, it appears to be a commonly missed step. In this case, the input name for step 3 and step 4 do not contain a wildcard character.

Implicitly Searching by Using a Wildcard

You can add an automatic wildcard search to the provider through web.config so that, if a user does not insert a wildcard character, the provider inserts it on the user's behalf. The following example shows the value you could enter to support the SQL Membership Provider (named AspNetSqlMembership) for automatic wildcard search.

<PeoplePickerWildcards>
  <clear />
  <add key=" AspNetSqlMembership" value="%" />
</PeoplePickerWildcards>

The following example shows the value you could enter to support the LDAP Membership Provider (named AdLdsLdapMembership) for automatic wildcard search.

<PeoplePickerWildcards>
  <clear />
  <add key="AdLdsLdapMembership" value="*" />
</PeoplePickerWildcards>

Managing Membership and Role Provider Identity Names in SharePoint Server or Windows SharePoint Services

When you configure the providers and give each a name (as in AspNetSqlMembership and AspNetSqlRole), SharePoint Server or Windows SharePoint Services prepends the identity (user or role name) with the appropriate provider name. If you then assign these identities to a site collection, the value is written to the UserInfo table in one of the content databases assigned to the Web application. For example, Table 2 shows a subset of the records from a content database where custom providers named AdLdsMembership and AdLdsRole are assigned, users and groups in SharePoint Server or Windows SharePoint Services are applied, and the name of the providers is changed to AdLdsLdapMembership and AdLdsLdapRole.

Table 2. Portion of a SharePoint UserInfo table

First Name or Second Name Logon Title Domain Group

Second

AdLdsLdapMembership:user02

user02

0

First

AdLdsMembership:user02

user02

0

Second

AdLdsLdapRole:readers

readers

1

First

AdLdsRole:readers

readers

1

Notice that SharePoint Server or Windows SharePoint Services stores all of these provider names, even though in the back-end repository there is only one user02 account and one readers role. Therefore, be sure to delete stale records from the UserInfo table if you change the provider names. In addition, you must reassign permissions after renaming the providers. Do not modify the UserInfo table directly. Instead, navigate to the People and Groups: All Groups page (/_layouts/groups.aspx) and delete the identities appended with the provider names that are old or not valid.

Searching for Roles

When you enable the Role Manager, the People Picker calls the RoleExists method of the Role Provider after calling the methods of the membership provider explored in the previous section. Now you should consider the following scenarios to better understand how this manifests itself in the People Picker's return results (see Figure 1 to identify interface locations in the People Picker):

  • You enter a specific role name in the People Picker and then click the Resolve button.

    SharePoint Server or Windows SharePoint Services validates the role name by calling the RoleExists method, and then underlines the validated role if RoleExists returns true.

  • No roles are specifically assigned in the site collection and you perform a search by using a specific role name.

    If the RoleExists method returns true, SharePoint Server or Windows SharePoint Services returns the role name appended with the role provider name (roleprovider:rolename) in the Account Name column.

  • You specifically assign a role in SharePoint Server or Windows SharePoint Services (that is, add the role as a member of a SharePoint group) and then search by using part of a role name (no wildcard).

    The RoleExists method returns false. Next, SharePoint Server or Windows SharePoint Services calls the UserInfo table, as we described in the previous section, and finds any matches for the partial group name and returns the role name appended with the role provider name (roleprovider:rolename) for the Account Name.

  • You attempt to search for a role name by using a wildcard for the underlying repository.

    This never returns a result because the Role Provider does not implement a method designed to return search results. The RoleExists method always returns false in this case, and SharePoint Server or Windows SharePoint Services does not search the UserInfo table for groups. There are two approaches you can take to handle how the People Picker behaves when it is tied to a custom membership and role provider. The nontechnical approach is to educate your user community that only searches using specific role names will work.

    For a technical solution that does not involve writing custom providers, you can derive a class from the EntityEditorWithPicker class to create a modified version of the People Picker (PickerEditor control). EntityEditorWithPicker is the base class of the PeopleEditor control. Within the OnInit method of this class, EntityEditorWithPicker creates the PickerDialog. The constructor of the PickerDialog requires, among other things, the PickerQueryControlBase class. The SharePoint Server or Windows SharePoint Services implementation of this is the SimpleQueryControl class. If you derive a class from SimpleQueryControl, you can override the IssueQuery method and control the behavior of the query within your custom PeopleEditor control. There is a fantastic blog by Igor Kozlov, Customizing EntityEditorWithPicker, that describes how to take this approach.

    This concludes part 1 of this article series.

    Next step: Identity and Access Strategies for SharePoint Products and Technologies (Part 2): Membership and Role Provider Assignment

About the Authors

Ethan Wilansky is a director in FTI Consulting's Technology Practice and focuses on creating custom SharePoint solutions. He is a member of the Office Developer Advisory Council.

Tomek Stojecki works at Annapolis Computing where he specializes in the architecture and development of Microsoft .NET Framework applications by using design patterns and agile methodologies. He has consulted on many SharePoint–based projects.

Additional Resources

For more information, see the following resources: