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

Summary: Explore how to configure the LDAP Providers in Microsoft Office SharePoint Server 2007, how to automate provider assignment and provider registration, and how to configure Web Single Sign On with Active Directory Federation Services (AD FS). This article is part 2 of 2. (22 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

  • SharePoint Server and the LDAP Providers

  • Properties of the LDAP Membership Provider

  • Example: Membership Section to Support AD LDS Instance

  • Properties of the LDAP Role Provider

  • Automating Custom Provider Assignment

  • Registering the Providers in web.config

  • Registering the Providers in SharePoint Central Administration

  • SharePoint Server and ADFS

  • User Life Cycle Management

  • Conclusion

  • About the Author

  • Additional Resources

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

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

SharePoint Server and the LDAP Providers

After reading Identity and Access Strategies for SharePoint Products and Technologies (Part 1): Membership and Provider Architecture, you should have a good idea of how the role and membership provider framework works in Microsoft SharePoint Products and Technologies (which includes Microsoft Office SharePoint Server 2007 and Windows SharePoint Services 3.0). Part 2 explores using the SharePoint built-in providers, such as the LDAP Provider.

Microsoft includes the LdapMembershipProvider and LdapRoleProvider classes in the Microsoft.Office.Server assembly in Office SharePoint Server. These classes are part of the Microsoft.Office.Server.Security namespace. You use these providers to access LDAP repositories, such as Active Directory Application Mode (ADAM)/Active Directory Lightweight Directory Services (AD LDS) or Novell eDirectory. (For examples of this capability, see Forms Authentication in SharePoint Products and Technologies (Part 3): Forms Authentication vs. Windows Authentication).

In this article, we focus on how to configure these providers to operate with AD LDS in Windows Server 2008. This configuration also works with ADAM. There are many articles and blog posts about this subject. Before you attempt to use the settings explored here, you should read about how to initially configure ADAM or AD LDS for interacting with Office SharePoint Server. For a good starting point, see Active Directory Lightweight Directory Services Overview (Microsoft TechNet).

However, full explanation of the various properties you must configure to make these providers work is hard to find. As of this writing, Microsoft has not made the Microsoft.Office.Server source code available. However, you can use the behavior of the Microsoft SQL Server Membership and Role Providers as your guide to understanding how their LDAP equivalents interact with SharePoint Server. In this article, we have done much of the groundwork for you by examining how the provider public methods interact with SharePoint Server, as described in this section.

First, consider the following example structure for LDAPMembershipProvider. Notice that many of the property settings, such as server and port, are empty. Read this section thoroughly because it ends with a completed configuration for an AD LDS instance.

Code Listing 2. LDAP Membership Provider example settings in web.config

<membership defaultProvider="AdLdsLdapMembership">
  <providers>
    <!--Remove any other membership providers that
    could be inherited by this Web application.-->
    <clear />
    <!--Support for LDAPMembershipProvider.-->
    <add name="AdLdsLdapMembership"
      type="Microsoft.Office.Server.Security.LDAPMembershipProvider, 
         Microsoft.Office.Server, 
         Version=12.0.0.0, 
         Culture=neutral, 
         PublicKeyToken=71E9BCE111E9429C" 
      server=" " 
      port=" " 
      useSSL=" "
      connectionUsername=" "
      connectionPassword= " "
      useDNAttribute = " "
      userDNAttribute=" " 
      userNameAttribute=" " 
      userContainer=" " 
      userObjectClass=" "
      userFilter=" " 
      scope=" "
      otherRequiredUserAttributes=" " 
    />
    <!--End support for LDAPMembershipProvider-->
  </providers>
</membership>  

The settings appear within the System.Web element of the web.config file for the target SharePoint Web application. Notice that the membership element includes a defaultProvider property. Within the extended Web application, you must set this to the value you specify for the added provider. Notice on line seven of the code example that a name is added for the provider. This name is arbitrary, but you should use something simple that communicates intent. This is particularly important because this name is appended to user account and role names in the People Picker when you perform a search for users or roles in the back-end repository. Another extremely important thing to remember is the use of Pascal casing on the property names in web.config. As with all XML configuration files, if you do not use the proper case for a property, its value is ignored by the underlying provider.

Properties of the LDAP Membership Provider

If you spend some time searching the Internet, you will find documentation giving you insight about the settings for this provider, but it is hard to find thorough explanations of how the provider uses these settings. It is also difficult to discern how these settings manifest themselves from within the SharePoint Web application interface. This section tries to answer those questions.

Server Bind and Connect Properties

Before you perform any search operations against an LDAP directory, you must first connect and then bind to it. The LDAP connection involves an endpoint address, such as a domain name/host name or server name and port value. The port value can be either fixed or assigned during setup, depending on the underlying directory. For example, in AD DS, you use either port 389 (unencrypted traffic) or 636 (port for transmitting SSL encrypted traffic) to establish a connection. In AD LDS, you initially configure an AD LDS instance with two ports, one for transmitting nonencrypted traffic and the other for transmitting encrypted traffic. For more information about AD LDS, see Active Directory Lightweight Directory Services Overview (Microsoft TechNet).

If you specify an encrypted port, you assign a server authentication certificate to the personal store of the service running AD LDS and set the UseSSL property to true. There are several additional steps necessary to get SSL communication working between SharePoint Server and AD LDS. For information about assigning a certificate to AD LDS, see Appendix A: Configuring LDAP over SSL Requirements for AD LDS. Also, be sure to read How to Enable LDAP Over SSL with a Third-Party Certification Authority (Article ID: 321051). This reference provides information about how to get a certificate configured to enable LDAP-S (LDAP over SSL) connections to AD LDS.

To configure AD LDS to enable LDAP over SSL from SharePoint Server, you must configure anonymous binding to AD LDS, as described in Allow Anonymous LDAP Binding to an AD LDS Instance. For example, if you have an AD LDS instance running on a computer named Server2008 and listening for an SSL connection on port 5004, then you could use the ADSI Edit snap-in to connect to the well-known Configuration container specifying Server2008:5004 in the Computer section of the ADSI Edit Connection Settings dialog box. Figure 2 shows the location of the Directory Service container.

Figure 2. Location of the Directory Service container in an AD LDS instance

Directory Service container in an AD LDS instance

Also, be sure to follow the instructions for adding the Anonymous Logon special Windows user account to the Readers role of the AD LDS instance.

By following these configuration adjustments, you should be able to authenticate to AD LDS over an encrypted (LDAP-S) connection. In summary, the LDAP membership provider uses the values specified for the server, port, and useSSL properties during the initial connection to the directory.

Following a successful connection, the LDAP Membership Provider performs an anonymous bind to the target directory. With the release of Microsoft Office SharePoint Server 2007 SP1, Microsoft added the connectionUsername and connectionPassword properties to the LDAP providers so that you can specify a user name and password for securely binding to a directory. Using SSL is particularly valuable in this case so that you encrypt the user name and provide it with a password as it crosses the wire during the bind operation.

The userDNAttribute and useDNAttribute Property Interactions

The value for the userDNAttribute property is the name of the directory attribute that identifies the user and user location in the underlying directory. For AD LDS or ADAM and AD DS, this attribute is named distinguishedName.

The LDAP Membership Provider relies on distinguished names of users for its operations (for example, authenticating a user). You can determine the attribute in the underlying directory that contains distinguished names for directory objects in one of two ways: You can provide the value by using the userDNAttribute property in web.config, or you can have the LDAP Membership Provider determine the value in the underlying directory. In the latter case, the LDAP Membership Provider bypasses the ADSI layer on which System.DirectoryServices relies and calls wldap32 native methods directly. The wldap32.dll is the Microsoft Win32 LDAP implementation. This approach is necessary in some cases when interacting with directories other than Microsoft directories.

The useDNAttribute property is the Boolean property you set in web.config to instruct the LDAP Membership Provider to determine whether to use a value you specify for the userDNAttribute property. By default, the useDNAttribute property is set to true in the constructor for this class.

The userContainer and scope Property Interactions

The userContainer property sets the starting point, in distinguished name format, for a user account search operation. If you have multiple containers below some level in your directory, userContainer should start at the parent of the user account hierarchy to successfully find the user accounts in subcontainers. For example, suppose you store your user accounts in organizational unit (OU) subcontainers (Customers, HR, and VIPMembers) of a parent container (CN) named Users, as shown in Figure 3. In this case, the userContainer property should be set to cn=users,dc=contoso,dc=com.

Figure 3. AD LDS example hierarchy as seen in ADSIEdit

AD LDS example hierarchy as seen in ADSIEdit

The scope property sets the depth of the search operation. The three allowed values from shallowest to deepest are Base, OneLevel, and Subtree.

Note

The casing of the value that you enter in web.config for any of these values is important. For example, entering Onelevel instead of OneLevel throws an ASP.NET configuration error when you attempt to authenticate to the SharePoint site.

To optimize your user account search operations, limit the scope as much as possible. Your choice of scope is determined mostly by the hierarchy of the target identity repository. In the previous example, if your user accounts are stored in the Customers, HR, and VIPMembers OUs and you set your userContainer value to the Users container (CN=Users), then you must set your scope at Subtree. This also accommodates subcontainers below the HR, Customers, or VIPMembers OUs. If you use a structure where you store all user accounts in the CN=Users container, then setting the scope to OneLevel will work. A Base scope is useful during a maintenance window when you want to ensure that only a single user can authenticate to the site. In this case, you set the userContainer value to a specific user account (for example, cn=user01,ou=hr,dc=contoso,dc=com).

The userNameAttribute Property

When the ValidateUser method runs, the membership provider uses the value of the name entered on sign-in and the directory attribute specified for the userNameAttribute property to return a string containing the actual value of the userNameAttribute in the underlying identity repository. If the name entered during sign-in and the value of the attribute specified for userNameAttribute finds a match, the ValidateUser method continues; otherwise, it returns false and authentication fails. For example, if the userNameAttribute is userPrincipalName and you enter user01@contoso.com for the logon user name, the ValidateUser method passes the entered value, the distinguishedName attribute, and the userPrincipalName attribute to a private method that retrieves the actual value of userPrincipalName for the user01 account.

Assuming this first step of authentication succeeds, ValidateUser performs additional validation such as checking that the user entered a password in the password field. The ValidateUser method relies on System.DirectoryServices, and thus Active Directory Service Interfaces (ADSI), to get a DirectoryEntry for the user object and perform a directory services fast bind to verify that the user can authenticate. If so, then a full bind operation occurs to get the underlying user object from the directory. At this point validation is complete.

The directory attribute specified for the userNameAttribute property also appears in the Welcome message at the top of your SharePoint site. Therefore, for ease of logon and for a friendly display after authentication and authorization are complete, consider using an attribute that stores a user-friendly value. For example, if you write e-mail addresses to the userPrincipalName attribute of a user account, you can use that to logon and it is the name that appears at the top of the screen, as shown in Figure 4.

Figure 4. SharePoint Welcome control displaying a friendly name

SharePoint Welcome control with friendly name

SharePoint Server also relies on userNameAttribute when it runs the GetUser method as part of the People Picker operation, as described earlier in Searching for Users. Figure 5 shows how the People Picker display might appear when performing a search for users whose names begin with user100.

Figure 5. People Picker displaying UserPrincipalName values

People Picker displaying UserPrincipalName values

The important point to remember here is that you should specify a userNameAttribute that is friendly to your users. For example, if the common name (cn) attribute for your user accounts is an alias that a user might not remember (or is otherwise not a user-friendly name), identify an attribute that returns a value that is easy to remember. In the previous example, the userPrincipalName in AD LDS could contain an e-mail address. It is not a mandatory attribute, nor is a properly formatted e-mail address required in AD LDS for this attribute. However, you can simplify specifying a userPrincipalName for your policy for new user accounts and make logon and identity search operations easier for your user community. Remember, if you decide to use an optional attribute, any user accounts you create without the attribute are not returned in a search request for authentication or authorization.

The userFilter and userNameAttribute Property Interactions

The userFilter property is the base portion of a search query filter you create to limit the types of objects that are included in search operations undertaken by the LDAP Membership Provider; for example, when the ValidateUser method runs to authenticate a user or when the GetUser method runs to get a user object for authorization. The query uses the LDAP search filter dialect as defined in RFC2254. For information about LDAP Search dialect, see Search Filter Syntax.

The value for this filter varies slightly from standard LDAP search filter syntax in two ways. First, it does not include the outer set of parentheses that you would typically include in an LDAP search filter expression that includes a logical operator. Second, when you want to create a logical AND of two search values, you must use a valid XML representation of an ampersand in the web.config file where this value is placed. For example, suppose you want to limit a search to user objects in AD DS or AD LDS. The LDAP filter for this is (&(objectCategory=person)(objectClass=user)). However, in the userFilter property you would enter &amp;(objectCategory=person)(objectClass=user—using "&amp;" in place of "&" and without the outer parentheses.

As mentioned in the previous section, the userNameAttribute property is the LDAP attribute that you supply to assist the ValidateUser method to find the user in the underlying directory. If you specify cn as your userNameAttribute (instead of the userPrincipalName as described previously), then within the LDAP search dialect, the membership provider inserts cn=<your common name> into the search request. If a user is assigned a cn of user01, then the LDAP dialect that the LDAP membership provider generates looks like the following.

(&(objectCategory=CN=Person,CN=Schema,CN=Configuration,

CN={F0E750BC-9603-4DB5-A21C76E05E150354})(objectClass=user)(cn=user01))

In the first condition of the AND expression, the LDAP Membership Provider expands the objectCategory=person element into the distinguished name of this schema element. (objectCategory=CN=Person,CN=Schema,CN=Configuration,

CN={F0E750BC-9603-4DB5-A21C-76E05E150354}).

You can see the LDAP search dialect that LDAPMembershipProvider constructs by using the Active Directory Diagnostics data collector set that is part of the Windows Server 2008 Reliability and Performance diagnostic tool in Server Manager. After authenticating as user01 and using the filter just described, a portion of the Active Directory Diagnostics report shows the following unique search (the table is split into the following three pieces, to fit this page).

Figure 6. Scope of search as specified in web.config is OneLevel

Scope of search in web.config is OneLevel

The scope of this search as specified in web.config is OneLevel. The provider converts this property to the syntax expected when System.DirectoryServices runs the search via the ADSI layer.

Figure 7. Provider search syntax

Provider search syntax

The provider creates the search dialect by combining the userFilter value with the userNameAttribute value and the name entered by the user.

Figure 8. Statistics about search operation

Statistics about search operation

Even with all of this background information about LDAP search filters, our testing found that you are better off circumventing the search filter by using (objectClass=*) as the value for this property. When you set the userFilter property to this value, the provider ignores the filter and instead creates a filter with the userNameAttribute alone. In our tests, an AD LDS directory with a few users and another with 15,000 users showed an initial authentication response time of less than 7 ms.

Note

After a user's initial authentication, response time is negligible for subsequent logons, as a result of caching. We recommend that you test this in your environment. The Windows Server 2008 Reliability and Performance feature is invaluable for this purpose.

The userObjectClass and Other RequiredUserAttributes Properties

Although the userObjectClass and RequiredUserAttributes properties appear in several blog entries and are two of the properties of LdapMembershipProvider, they appear to be used only by the CreateUser public method. This is not a call SharePoint Server makes by default. This method is specifically designed to support user account provisioning.

Note

Because the CreateUser method is obfuscated, this article only suggests this purpose based on the method's name.

Example: Membership Section to Support AD LDS Instance

Now you should have a good sense of how the LDAP Membership Provider uses these properties. Following is a membership section example to support an AD LDS instance (be sure to read the previous section before you review this example):

  • The membership element appears inside of the system.web element.

    Ensure that you include the defaultProvider property. You specify the name of the default provider when you configure forms authentication for this Web application in SharePoint Central Administration.

  • In this case, the clear element ensures that if other membership providers are specified in machine.config, it will not conflict with this membership declaration.

    By default, SqlMembershipProvider appears in machine.config. Including the clear element removes the SqlMembershipProvider provider from this Web application's inheritance chain.

  • The add element is the heart of the property configuration for the provider.

    In addition to the properties that we explored for the LDAP Membership Provider, this element contains the name property whose value matches the defaultProvider property specified on the membership element, and the type property.

    The type property is a comma-delimited assembly declaration for the provider. The first part is the fully qualified namespace to the LDAPMembershipProvider class followed by the assembly (.dll) that contains this class. Typically, Microsoft names their assemblies after a core part of the namespace (in this case Microsoft.Office.Server).

    The Version, Culture, and PublickKeyToken subproperties of the type property declare characteristics of the assembly that are set at compile time.

    Note

    Despite the change in the assembly from Microsoft Office SharePoint Server 2007 and Microsoft Office SharePoint Server SP1, this assembly declaration is unchanged.

The remaining properties of the add element provide values for the Initialize method of the LDAPMembershipProvider class, and are described in detail immediately before this section. Be aware that Microsoft provides some default values in the constructor of the LDAPMembershipProvider class.

Code Listing 3 is a complete example of a web.config membership element that focuses on the properties that are important for interacting with AD LDS. In this example, the LDAPMembershipProvider class is instructed to use the following:

  • SSL to encrypt communication between SharePoint Server and AD LDS

  • Anonymous bind because no user name or password is specified

  • The userPrincipalName attribute of AD LDS user account to simplify authentication and search operations

  • A userContainer of cn=users,dc=contoso,dc=com to point the provider as close as possible to the user accounts that will authenticate to this instance of SharePoint Server

  • A userFilter that, in our test scenarios, provided better performance than that provided by the more specific filters

  • A scope to accommodate user accounts stored in OUs below the Users container

Code Listing 3. LDAP membership provider example settings in web.config

<membership defaultProvider="AdLdsLdapMembership">
  <providers>
    <!--Remove any other membership providers that
    could be inherited by this Web application.-->
    <clear />
    <!--Support for LDAPMembershipProvider.-->
    <add name="AdLdsLdapMembership"
      type="Microsoft.Office.Server.Security.LDAPMembershipProvider, 
         Microsoft.Office.Server, 
         Version=12.0.0.0, 
         Culture=neutral, 
         PublicKeyToken=71E9BCE111E9429C" 
      server="LD830" 
      port="5003" 
      useSSL="true" 
      userDNAttribute="distinguishedName" 
      userNameAttribute="userPrincipalName" 
      userContainer="cn=users,dc=contoso,dc=com" 
      userFilter ="(objectClass=*)" 
      scope="Subtree"
    />
    <!--End support for LDAPMembershipProvider.-->
  </providers>
</membership>  

Properties of the LDAP Role Provider

The properties required by the LDAP Role Provider for connecting and binding to an underlying LDAP repository are identical to the LDAP Membership Provider. Therefore, we will not explore those properties again here. The remaining properties are different, however, and many are essential to the operation of this provider. For a review of what role providers do in SharePoint Server, see "How SharePoint Uses the Membership and Role Providers" in Identity and Access Strategies for SharePoint Products and Technologies (Part 1): Membership and Provider Architecture. In addition to the connect-related and bind-related properties of the LDAP Role Provider, this article explores how this provider uses the other properties you can set in web.config.

The cacheDurationInMinutes Property

Microsoft improved the LDAP Role Provider with the release of Microsoft Office SharePoint Server SP1 by adding a role caching mechanism. Now, roles are cached on a per-user basis with the use of the LdapRoleProviderCache class. This is likely designed to improve authorization performance after roles are initially retrieved for a user. The cache duration is set initially to 30 minutes. Increasing this value improves authorization performance, but also uses more memory resources on your front-end Web servers to maintain cache data.

The useUserDNAttribute and dnAttribute Property Interactions

The LDAP Role Provider relies on distinguished names of users and groups for its operations (for example, retrieving roles for a specific user account object). You have two options for determining the attribute in the underlying directory that contains distinguished names for directory objects: You can provide the value by using the dnAttribute property in web.config, or you can have the LDAP Role Provider determine the value in the underlying directory. In the later case, the LDAP Role Provider bypasses the ADSI layer on which System.DirectoryServices relies and calls wldap32 native methods directly. The wldap32.dll is the Microsoft win32 LDAP implementation. This approach is necessary in some cases when interacting with non–Microsoft directories.

The useUserDNAttribute property is the Boolean property you set in web.config to instruct the LDAP Role Provider about whether to use a value you specify for the dnAttribute property. By default, the useUserDNAttribute property is set to true in the constructor for this class, therefore the dnAttribute is read by the provider.

Note

Although the LDAP Membership Provider reads the useDNAttribute Boolean property in web.config, the LDAP Role Provider reads the useUserDNAttribute Boolean property. Be careful not to confuse these properties.

The userNameAttribute Property

The LDAP Role Provider uses the value in the userNameAttribute property to construct a search filter for its search operations, in this case, when ultimately calling the GetRolesForUser public method. As mentioned in "Authorization" in Identity and Access Strategies for SharePoint Products and Technologies (Part 1): Membership and Provider Architecture, the provider uses this method to verify that a user is a member of a role that is authorized to access the target location.

The groupNameAttribute Property

When the LDAP Role Provider collects a list of roles for a user, it returns the value of the attribute that you specify for this property. For example, if a user is a member of the following two roles…

cn=group01,ou=HR,dc=contoso,dc=com (cn=group01)

cn=group02,ou=Admin,dc=contoso,dc=com (cn=group02)

…then setting the groupNameAttribute property to cn will return group01 and group02 to the caller in a string array (named roleNames) for the user.

The groupMemberAttribute, groupFilter, groupContainer, and scope Property Interactions

When the GetRolesForUser method runs to retrieve all the roles assigned to a user, a private method constructs a search filter from the values specified for groupMemberAttribute, groupFilter, and the distinguished name of the user. Consider the following example settings in web.config.

groupFilter = "(objectCategory=group)"

groupMemberAttribute = "member"

As a result, the LDAP Role Provider constructs the following filter for user01 located in the users\HR ou in the contoso.com domain.

(&(objectCategory=group)(member="cn=user01,ou=HR,cn=users,dc=contoso,dc=com"))

Next, the provider uses the value you specify for groupContainer and scope to analyze all of the groups within the specified parameters. If you store your groups in a single Roles container in the Contoso domain (contoso.com), then the following properties allow the provider to analyze the groups in this container.

groupContainer = "cn=roles,dc=contoso,dc=com"
scope = "OneLevel"

However, if you store your user accounts in a hierarchy deeper than a scope of onelevel, then you must set this scope property to Subtree. If you do not, users who are granted access through their membership in AD LDS groups will authenticate to SharePoint Server, but will not be authorized to view the site content. For more information about properly setting the scope value, see The userContainer and scope Property Interactions.

The userFilter Property

The userFilter value is necessary only when useUserDNAttribute is set to false. (For more information about the useUserDNAttribute property, see The useUserDNAttribute and dnAttribute Property Interactions). Briefly, the userFilter property contains a user filter in LDAP dialect. For example, (&(objectCategory=person)(objectClass=user)) written as &amp;(objectCategory=person)(objectClass=user) in web.config.

When the LDAP Role Provider makes native LDAP calls (by using the wldap32.dll directory) to identify the distinguished name attribute of a user object and retrieve its value, it passes the value of userFilter in and the supplied userNameAttribute value; for example, (&(objectCategory=person)(objectClass=user)(userPrincipalName=user01@contoso.com)). The userFilter portion of the LDAP dialect is designed to improve the query performance of this search by limiting the analysis to a specific user account object.

The userContainer Property

The userContainer value identifies the distinguished name of a container where you store your user accounts or the starting point of your user account hierarchy. This value is usually the same value that you specify for the same named property of the LDAP Membership Provider.

After the LDAP Role Provider locates the target user account by distinguished name, it returns the roles to which the user belongs.

The groupNameAlternateSearchAttribute Property

The RoleExists method uses the groupNameAlternateSearchAttribute property to return matching role names to the People Picker. We are assuming that this is the purpose of this property because the RoleExists method is obfuscated in LDAPRoleProvider. For information about how the People Picker uses this method, see "Searching for Roles" in Identity and Access Strategies for SharePoint Products and Technologies (Part 1): Membership and Provider Architecture.

A Role Provider Configuration Example

As for the LDAP Membership Provider, you have now completed a similar examination of how the LDAP Role Provider uses these properties. The following is a roleManager section example to support a SharePoint Web application connected to an AD LDS instance, as shown in Figure 7 (be sure to read the previous section before reviewing this example). The example shows the following:

  • The roleManager element appears inside of the system.web element.

    Ensure that you include the defaultProvider property with this tag. You specify this name when you configure forms authentication for this Web application in SharePoint Central Administration. Also, the value of the role manager defaultProvider is necessarily different in the Web application hosting Central Administration. For information about this important configuration difference, see the Where Do The Providers Belong.

  • In this case, the clear element ensures that if other role providers are specified in machine.config, they will not conflict with this roleManager declaration.

    By default, there are two role mangers appearing in machine.config. Including the clear element removes AspNetSqlRoleProvider and AspNetWindowsTokenRoleProvider from this Web application's inheritance chain.

  • The add element is the heart of the property configuration for the provider.

    In addition to the properties that were explored for the LDAP Role Provider, this element contains the name property whose value matches the defaultProvider property specified on the roleManager element and the type property.

    The type property for the LDAP Membership Provider and its properties are described earlier in Example: Membership Section to Support AD LDS Instance. The only difference here is that the fully qualified class is Microsoft.Office.Server.Security.LDAPRoleProvider.

The remaining properties of the add element provide values for the Initialize method of the LDAPRoleProvider class and are described in detail in Properties of the LDAP Role Provider. In addition, Microsoft includes default values for some of the properties in the constructor of the LDAPRoleProvider class.

Code Listing 4 provides an example of a web.config roleManager element that optimizes on the properties that are important for interacting with AD LDS. In this example, the LDAP Role Provider is instructed to use the following:

  • SSL to encrypt communication between SharePoint Server and AD LDS for role management

  • Anonymous bind because no user name or password are specified

  • The userPrincipalName attribute of an AD LDS user account for including in search operations that ultimately retrieve the roles assigned to the target user

  • The distinguishedName attribute to clearly identify the target user for role retrieval

  • The cn=roles,dc=contoso,dc=com container to return the cn (groupNameAttribute) of any group where the target user is found in the member attribute of the group

  • A Subtree scope to perform a deep search (subtree scope) to accommodate a user account hierarchy below cn=users,dc=contoso,dc=com

  • A group filter that targets only group directory objects in the search for role membership

Code Listing 4. LDAP Role Provider example settings in web.config

<!--Added the role manager to support roles in AD LDS.-->
<roleManager enabled="true" defaultProvider="AdLdsLdapRole">
  <providers>
    <!--Remove any other role providers that are inherited.-->
    <clear />
    <!--Support for LDAPRoleProvider.-->
    <add name="AdLdsLdapRole"
      type="Microsoft.Office.Server.Security.LDAPRoleProvider,
          Microsoft.Office.Server, 
          Version=12.0.0.0,
          Culture=neutral,
          PublicKeyToken=71e9bce111e9429c"
      server="LD830"
      port="5003"
      UseSSL="true"
      userNameAttribute="userPrincipalName"
      userContainer="cn=users,dc=contoso,dc=com"
      userFilter="&amp;(objectClass=user)(objectCategory=person)"
      dnAttribute="distinguishedName"
      useUserDNAttribute="true"
      groupContainer="cn=roles,dc=contoso,dc=com"
      scope="Subtree"
      groupNameAttribute="cn"
      groupMemberAttribute="member"
      groupFilter="&amp;(objectCategory=Group)(objectClass=group)"
    />
    <!--End support for LDAPRoleProvider.-->
  </providers>
</roleManager>
<!--End Added the role manager to support roles in AD LDS.-->

Automating Custom Provider Assignment

The task of configuring custom providers can be both time consuming and error prone. It becomes even more apparent when working in a Web farm environment, where some of the settings might have to be replicated across multiple Web applications. This section explores where you need to place configuration settings for the membership and role providers, and then shows you how to use existing tools and SharePoint APIs to help alleviate the pain of manual configuration.

Where Do The Providers Belong

Numerous examples describe how to configure security for a Web application by using the provider model, some of which are included in Additional Resources. Most of the configuration examples explore how to make membership provider assignments for three SharePoint Web applications: primary, extended, and Central Administration. Although it is fairly common in real-world applications to modify all three Web applications, not all of these Web applications need to support the custom membership provider. In addition, many of the examples ignore the role provider altogether, although using groups in SharePoint Server or Windows SharePoint Services is essential for scaling user management to support many users. This section explains the purpose that both the membership and role providers play in various Web application targets.

Consider three targets when configuring Web application security in SharePoint Server or Windows SharePoint Services by using the membership and role providers. The first target is the extended Web application, which is a mandatory target when following the most common custom provider setup involving a primary Web application extended to support custom providers. The other two targets are the primary Web application and the Central Administration Web application. Configuring both of these Web application targets (primary and Central Administration) is optional.

Mandatory Target 1: Modifying the web.config of a SharePoint extended Web application

The extended Web application takes full advantage of the provider model by taking advantage of its capabilities for authentication, authorization, and search within the underlying identity repository. Following are the two essential steps in the process:

  1. Assign both providers in web.config.

  2. Configure forms authentication in SharePoint Server or Windows SharePoint Services.

This is the only required Web application target to take advantage of a custom provider by using forms authentication in SharePoint Server or Windows SharePoint Services.

After you configure the extended SharePoint Web application, you must give accounts in the custom repository access to the extended Web application by assigning them (either users or groups) to SharePoint groups. You can modify two Web application targets to complete the assignment task, as follows.

Optional Target 2: Modifying the web.config file of a primary Web application

After you complete this modification, you log on to the primary Web application by using Windows Integrated Authentication. You then assign users or groups in the identity repository to which the provider is connected to one or more SharePoint groups.

Optional Target 3: Modifying the web.config file of the Central Administration Web application

After you complete this modification, you log on to the Central Administration Web application and configure Web application policies for the extended Web application. You view and administer the policies for the Web applications in SharePoint Central Administration (click Application Management, and then click Policy for Web application). After you select the extended Web application's zone, you are presented with the People Picker control and the list of predefined permissions, as shown in Figure 9.

Figure 9. Web application policy assignment in Central Administration

Web application policy assignment

Within the People Picker, you select valid users or groups from the identity repository to which the provider is connected, select a permission or permissions, and then click Finish.

An important caveat is that, when you assign a role provider in the Central Administration web.config, be sure to set the default role provider to AspNetWindowsTokenRoleProvider, which is the name of the WindowsTokenRoleProvider configured in the machine.config file. This ensures that the Central Administration Web application continues to rely on Windows groups to authorize access to the Central Administration interface, while at the same time enabling the People Picker to resolve identities through the custom role provider.

Note

It is less common, but achievable, to make the primary Web application the target for custom provider setup instead of using an extended Web application. If you choose this model, you use optional target 3, the Central Administration Web application, to configure Web application policy for the target primary Web application. You accomplish this step by adding a user or group from the custom identity repository and granting that principal full control to the primary Web application via Web application policy (see Figure 9). Finally, you log on to the primary Web application with the assigned user or a user who is a member of the assigned group. After you are inside of the primary Web application, you grant other users from the custom repository access to SharePoint Server or Windows SharePoint Services via SharePoint groups. To support this model, you must register the providers in both the primary Web application and in Central Administration.

Registering the Providers in web.config

The SharePoint object model contains the SPWebConfigModification class in the Microsoft.SharePoint.Administration namespace. This class provides a powerful and managed way to automate the addition of modifications to and removal of modifications from web.config. In addition to the benefit of automation, this class registers the change inside of SharePoint Server or Windows SharePoint Services so that SharePoint Server or Windows SharePoint Services manages and enforces the change. For more information about how to use the SPWebConfigModification class, see Automate Web App Deployment with the SharePoint API.

There are two Stsadm.exe extensions in the code sample project that accompanies this article (Identity and Access Strategies Code Sample for SharePoint Products and Technologies) that show how to use the SPWebConfigModification class to configure the SQL Membership and Role providers. If you already deployed the solution accompanying this article, then these two additional Stsadm.exe extensions are available in your SharePoint instance.

You can easily modify these classes to configure any other custom provider by changing the string values to reflect provider-specific properties. Alternatively, you could use this code as a basis for building a SharePoint Feature scoped at a Web application level, thus giving you more control over the deployment process. When you activate the Feature, the provider settings can be deployed and when you deactivate the Feature, the settings can be retracted.

Before digging into this code, a critical caveat is that SharePoint Server or Windows SharePoint Services views all of the Web applications (both the primary and the extended Web application) as the target for these Web configuration updates. Therefore, if you plan to use different membership and role providers in the Web applications, consider registering these updates by using the SPWebConfigModification class.

In "Programmatically Viewing the Provider Architecture in SharePoint Products and Technologies" in Identity and Access Strategies for SharePoint Products and Technologies (Part 1): Membership and Provider Architecture, we reviewed the basics of writing custom Stsadm.exe extensions. Now you can learn the specifics of the provider configuration. The AddWebConfigModifications method creates an instance of the SPWebConfigModification class for each XML element or attribute and applies the updates to the web.config file of a target SharePoint Web application, as shown in Code Listing 5:

  1. Call the Add method of the WebConfigModifications class to ensure the addition of the membership element.

    ModificationHelper is a simple class included with the code sample that encapsulates the creation of the SPWebConfigModification object.

  2. Call the Add method of the WebConfigModifications class to ensure the addition of the providers element.

    If a user specifies the default parameter when running the stsadm command that calls this method, then call the Add method of the WebConfigModifications class to add the defaultProvider attribute to the providers element.

  3. Call the Add method of the WebConfigModifications class to add the custom provider.

    The input parameters of the AddWebConfigModifications method supply the provider name, application name, and SQL Server connection string name to this custom provider operation.

  4. Call the ModificationHelper.ApplyModifications method to apply the modifications to the target web.config file and register the updates in the SharePoint configuration database.

Code Listing 5. Creating web.config modifications for the Membership Provider

private void AddWebConfigModifications(SPWebApplication webApp, 
    string providerName, string applicationName, string connectionStringName)
{
    // Ensure membership tag.
    webApp.WebConfigModifications.Add(
        ModificationHelper.CreateModificationForElement(
            owner,
            "configuration/system.web",
            "membership",
            "<membership></membership>"
        )
    );

    // Ensure providers tag.
    webApp.WebConfigModifications.Add(
        ModificationHelper.CreateModificationForElement(
            owner,
            "configuration/system.web/membership",
            "providers",
            "<providers></providers>"
        )
    );

    // Optionally, set as a default provider.
    if (setAsDefault)
    {
        // Set default provider attribute.
        webApp.WebConfigModifications.Add(
            ModificationHelper.CreateModificaitonForArgument(
                owner,
                "configuration/system.web/membership",
                "defaultProvider",
                providerName
            )
        );
    }

    // Add custom provider tag.
    webApp.WebConfigModifications.Add(
        ModificationHelper.CreateModificationForElement(
            owner,
            "configuration/system.web/membership/providers",
            String.Format("add[@name='{0}']", providerName),
            String.Format(
               @"<add name='{0}'
               applicationName='{1}'
               connectionStringName='{2}'
               type='System.Web.Security.SqlMembershipProvider,
               System.Web,
               Version=2.0.3600.0, 
               Culture=neutral, 
               PublicKeyToken=b03f5f7f11d50a3a' 
               />", 
               providerName, applicationName, connectionStringName)
        )
    );            
    
    ModificationHelper.ApplyModifications(webApp);   
}

Note

The ApplyModifications method of the ModificationsHelper class makes the following two SharePoint calls on the SPWebApplication object named webApp.

webApp.Farm.Services.
    GetValue<SPWebService>().
        ApplyWebConfigModifications();
webApp.Update();

It is important that you are able to add and to remove managed web.config settings. Manually removing the entries from web.config does not suffice because the next time Windows SharePoint Services starts, manually removed, managed settings are re-added.

RemoveWebConfigModifications in Code Listing 5 revokes the modifications by inspecting the Owner property. The idea was originally authored by Vincent Rothwell and this article includes the URL of the blog post in the Additional Resources.

  1. Iterate through the collection of the SPWebConfigModification elements associated with the specific SPWebApplicaion object.

    The order of the for loop is reversed to allow for removal of the elements from the collection while iterating through it.

  2. Compare the Owner property, which is assigned a unique string value by using a global constant outside of this method.

    See the code download that accompanies this article for details about how the owner value is being set. The approach in this article ensures that only the modifications created by a specific owner are removed.

  3. After the elements of the WebConfigModifications are removed, run the previously described ApplyModifications helper method of the ModificationHelper class to apply the changes in SharePoint Server.

Code Listing 6. Removing modifications by owner

private void RemoveWebConfigModifications(SPWebApplication webApp)
{
    int count = webApp.WebConfigModifications.Count;

    // Remove all modification where the owner matches.
    for (int i = count - 1; i >= 0; i--)
    {
        SPWebConfigModification mod = webApp.WebConfigModifications[i];
        if (mod.Owner.Equals(owner))
            webApp.WebConfigModifications.Remove(mod);
    }

    if (count > webApp.WebConfigModifications.Count)
    {
        ModificationHelper.ApplyModifications(webApp);
    }
}

In the accompanying code download, you will see the same two methods in the SqlRoleProviderConfig class. SqlRoleProviderConfig handles the configuration of the RoleManager element in web.config.

After being deployed, the following two commands are available in Stsadm.exe:

  • sqlmembershipproviderconfig

  • sqlroleproviderconfig

Important

If you decide to take advantage of this automated provider registration approach, be sure to thoroughly test it in an expendable SharePoint environment. An improper configuration assignment can result in a severe Web application failure. Another important prerequisite is verifying that you have a plan to restore the system to its previous state in the event of a catastrophic failure.

Just as you would with any Stsadm operation, you run the command by passing Stsadm.exe the name of the operation to perform and various parameters associated with the command. For example, to configure the SQL Server Membership Provider for the www.contoso.com extended Web application and set the default provider to fbaMembers with a connection string name of fbaConnection and an application name of" /", run the following command from a command-line prompt.

stsadm -o sqlmembershipproviderconfig -url "https://www.contoso.com"

-providerName "fbaMembers" -default -connectionStringName "fbaConnection" -applicationName "/"

This code does not register a connection string for the SQL Server Membership Provider or add the PeoplePickerWildcards element. You can either automate the inclusion of these strings by using the code just described or add them manually. Other providers, such as the LDAP Membership Provider, do not include a connection string element.

Similarly, to configure the SQL Server Role Provider with the name of fbaRoles, connection string name of fbaConnection, and an application name of "/", and to set it as a default role provider, run the following command from a command-line prompt.

stsadm -o sqlroleproviderconfig -url "https://www.contoso.com" -providerName "fbaRoles" -default -connectionStringName "fbaConnection" -applicationName "/"

To revoke the modifications, use the remove attribute with either operation, splmemberproviderconfig or sqlroleproviderconfig. The following is an example using the sqlroleproviderconfig operation:

stsadm -o sqlroleproviderconfig -url "https://www.contoso.com" -remove

Note

If you name your providers as they are named in this article (AspNetSqlMembershipProvider and AspNetSqlRoleProvider), you must add the <clear /> element inside of each providers element so that the same named provider in machine.config does not cause conflict.

Registering the Providers in SharePoint Central Administration

To complete the task of registering the providers manually within SharePoint Central Administration, navigate to Application Management, click Authentication Providers, and then click Edit Authentication for the specific Web application zone, and then set the membership and role provider, as shown in Figure 10.

Figure 10. Edit Authentication page in Central Administration

Edit Authentication page in Central Administration

Microsoft provides a simple way, by using Stsadm.exe, for configuring these settings by using the authentication operation. Considering the settings shown in Figure 10, the following is the equivalent Stsadm command.

stsadm -o authentication -url https://www.contoso.com -type Forms

-membershipprovider AspNetSqlMembershipProvider -rolemanager AspNetSqlRoleProvider

The following is the equivalent command for the LDAP provider configuration explored earlier.

stsadm -o authentication -url https://www.contoso.com -type Forms

-membershipprovider AdLdsLdapMembership -rolemanager AdLdsLdapRole

Note

For the -url parameter, you should target the URL that you specified for the extended Web application. In this example, the primary Web application is available internally as http://ossrtm and the extended Web application is available in the Internet zone at https://www.contoso.com.

You can read more about this operation in Authentication: Stsadm operation (Office SharePoint Server) on Microsoft TechNet.

SharePoint Server and ADFS

In "Membership and Role Provider Architecture in SharePoint Server and Windows SharePoint Services" in Identity and Access Strategies for SharePoint Products and Technologies (Part 1): Membership and Provider Architecture, we mentioned the SingleSignOnMembershipProvider2 and SingleSignOnRoleProvider2 provided by ADFS. These providers enable you to take advantage of ADFS to make SharePoint Server a claims-aware or claims-based application. Users with a valid claim can then logon to a SharePoint instance. A common use of this capability is to allow users in other organizations to logon to your instance of SharePoint Server with a user account in their identity repository. This is an oversimplification of the technology, but should give you an idea of its power.

Before you attempt to make a SharePoint instance claims-aware, you must get an ADFS infrastructure in place. Then, ADFS can be configured with federated trust relationships for any partner organization that has a WS-Federation compliant federation server (most major federation vendor products have WS-Federation support built-in). With the federation relationship in place, identities from those partners can be trusted to access the SharePoint Server 2007 site.

Note

For a great overview of ADFS and how it provides a service that cannot be provided by Active Directory alone, see Active Directory Federation Services (ADFS) for ASP.NET 2.0 Developers. This is Donovan Follette's blog, a Microsoft Windows Server Identity and Access Management evangelist. Donovan also provides two excellent screencasts by Keith Brown that can help you understand how to take advantage of this technology.

Whether or not you have experience with ADFS, the ASP.NET provider model that this article explored using the SQL Server and LDAP providers also applies to the ADFS providers. The same provider methods are called by SharePoint Server and you make the same types of modifications to SharePoint Web application web.config files. However, there are two differences in configuration because the ADFS provider uses Web single sign on (WebSSO) instead of forms authentication in SharePoint Server.

Difference 1: WebSSO Authentication Provider

When configuring an authentication provider in SharePoint Central Administration for an ADFS-enabled SharePoint Web application, you choose Web single sign on instead of forms, as shown in Figure 11.

Figure 11. Authentication Provider page for an ADFS-enabled Web application

Authentication Provider page

Note

The names SingleSignonMembershipProvider2 and SingleSignonRoleProvider2 in Figure 11 happen to match the names of the ADFS membership and role provider classes, but this is not required. The key point is that the application names registered for these providers in web.config must match the names specified on the Edit Authentication page (Code Listing 6).

Difference 2: Enabling WebSSO in web.config

For a SharePoint Web application to become claims-aware, you must enable ADFS WebSSO in the target Web application's web.config file. This allows the ADFS WebSSO engine to insert itself into the ASP.NET Request Pipeline. For a detailed explanation about each section you add to web.config, see Active Directory Federation Services.

User Life Cycle Management

One area where the potential of the membership and role providers is not fully realized in SharePoint Products and Technologies is in their ability to create and delete users and roles in the underlying repositories. Even though both providers define the signatures for the methods that handle those operations, SharePoint Server and Windows SharePoint Services lack the user interface (UI) needed to support this functionality. As a result, to provision user accounts in SharePoint Server you need knowledge about the tools to manage the identity repository of choice and knowledge about the SharePoint security model. For example, to provision an AD LDS user account in SharePoint Server, you use the ADSI Edit snap-in to create an account in the identity store. You then grant the account permissions in SharePoint Server.

Combining these two activities takes the burden off of the network administrator and provides for a time-saving and cost-effective way of registering users to the portal. You can achieve this by either building a custom provisioning component or by using an offering from a third-party solution vendor.

If you choose to develop a custom solution that takes advantage of the provider model, your presentation layer controls call provider methods. For the task of creating and deleting accounts, use the CreateUser and DeleteUser methods of the membership provider. Managing roles in your custom solution requires the CreateRole, AddUsersToRoles, RemoveUsersFromRoles, and DeleteRole methods of the role provider. For building a Web UI, you can use the ASP.NET version 2.0 (or later) suite of controls that are designed to call the providers.

If you would like to start from existing code for your UI, consider starting with an open source project, such as the Community Kit for SharePoint. This project includes the IEE (Internet Extranet Edition) Forms Based Authentication Solution with a series of Web Parts designed to handle common membership-related tasks. For example, the Membership Request Web Part handles user registration and enables a portal administrator to review and approve requests.

If all you need is an interface to easily create and manage users and roles for the purpose of testing and debugging the providers, consider using the built-in Web site administration tool in Microsoft Visual Studio 2005 and Visual Studio 2008. Another alternative is the Membership Seeder. This is a Windows-based application also released as part of the Community Kit for SharePoint.

Conclusion

This article describes ways in which you can configure one or more custom providers in SharePoint Products and Technologies, and how you can accomplish this task. If you have a solid understanding of how SharePoint Server and Windows SharePoint Services use the ASP.NET membership and role provider architecture, you have the knowledge to better understand provider behavior, how to troubleshoot issues with the providers, and how to write your own custom provider.

About the Author

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: