Monday, May 19, 2008

HOWTO: Configuring a Office SharePoint Server 2007 Publishing Site with Dual Authentication Providers and Anonymous Access


Content-centric sites that are managed via a Content Management System typically have very specific requirements. The owners of the content of a content-centric site usually spend most of their time behind the company firewall and login to their corporate Active Directory. Ideally these users need to have a single-sign-on (SSO) experience where they don't have to remember a special username and password to simply login to a Content Management System to author and manage the content on the company Web site. The public-facing portion of the site needs to allow visitors to browse the site anonymously. However, there may be certain areas of the site that require the user to login. These may include premium content, registration, or an e-commerce solution. While the familiar username/password dialog is acceptable in a corporate setting, it is frowned upon on the public realm of the Internet. Therefore, many companies prefer to implement some type of forms authentication where users login using a username or email address and password to gain access to protected areas.

Web Content Management (WCM), one piece in the Enterprise Content Management (ECM) strategy included in Microsoft Office SharePoint Server (MOSS) 2007 adds the capability of hosting and managing content-centric sites to the SharePoint platform. MOSS 2007 is built on top of Windows SharePoint Services (WSS) v3 which is in turn built on top of ASP.NET 2.0. This means that WSS v3 (and MOSS 2007) have full access and utilize everything that ASP.NET 2.0 has to offer… including the pluggable authentication model. It is this pluggable authentication that I will leverage to provide multiple authentication options for a single Web site. In this article I want to demonstrate how to configure a Publishing Site (aka: WCM site) in MOSS 2007 for the previously described common scenario companies encounter with content-centric sites. The goal is to provide an experience that achieves three requirements:

Allow content owners/authors to authenticate on the site using their corporate Active Directory credentials in order to manage the Web site's content.
Allow unauthenticated, anonymous users, to browse the unrestricted areas of the Web site.
Require anonymous user to provide a friendly Web-based form to login in order to consume restricted content.
I'll demonstrate how all three goals can be achieved using MOSS 2007 and WSS v3 in this article. First I'll set up a database to store the information for users accessing the Web site from the Internet. Once that's configured, I'll create two Web applications and a Publishing Site; each Web application, or IIS Web site, will be configured for a specific type of authentication mechanism (Windows Authentication [AD] and Forms Authentication). Then I'll configure both Web applications so they can access the users and roles that will be granted rights within the site (typically read or contribute rights to protected areas of the site). Once both sites are configured to communicate with the forms authentication-based user and role store, I'll configure one Web application to allow users to sign-in and authenticate via a common Web-based form. The last step will be to configure the site for anonymous access so they can browse the site and consume the content. Finally, I'll show you how to require a login for a specific area of the site.

This article is not written as a step-by-step instruction manual on how to configure your site for anonymous access with dual authentication mechanisms. It assumes some experience with WSS v3 and MOSS 2007. While the subject of this article deals with configuring a Publishing Site (aka: Web Content Management Site), everything translates to any type of WSS v3-based site including MOSS sites.

Setting Up ASP.NET 2.0 Forms Authentication User & Role Data Store



Before we can do anything, we first need to create a database that will store all the information, credentials, roles, and users for the forms based authentication site. Then we'll add a single user to this database which we'll use for testing later. Nothing in this step has anything to do with SharePoint as its just plain ASP.NET 2.0.

Create the ASP.NET 2.0 Database

Before we can do anything else, we need to create a database that will store the users and roles. Microsoft has provided a utility, aspnet_regsql.exe, that will create this database for you. It can be found here: %windir%\Microsoft.NET\Framework\v2.0.5027. Executing this file will trigger a wizard that will walk you through creating the ASP.NET 2.0 database. I've named my database AcAspNetDb and configured it for Windows Authentication, as shown in Figure 1 below.






Figure 1 – aspnet_regsql.exe wizard (click for larger image)

Configure Membership & Role Providers

Now that our database is configured, we need to add a single user. In my opinion, the best way to do this is to create a new Web site project in Visual Studio 2005. Why? Because not only does it have an easy way to access the ASP.NET 2.0 administration Web site that will let us add users and roles, but we'll also ensure our database connection strings, membership, and role providers are correctly configured before we bring SharePoint into the equation. I'll use these same connection string and providers in the SharePoint sites later… so we have a good foundation to copy from.
Open Visual Studio 2005 and select File -> New -> Web Site. In the New Web Site dialog, select the template ASP.NET Web Site, set the location to File System. I like to put all my Web sites in the [drive]:\Inetpub directory so I'll put mine in the following directory: [drive]:\Inetpub\AC FBA Utility Site (FBA = Forms Based Authentication). The language is irrelevant so you can pick anything… we won't write a single line of code.




Now, add a web.config file to the site. By default, you'll see a <connectionStrings /> node within the <configuration> node. Here you want to specify a connection string to the database you just created in the previous step. For me, I'll replace the node with the following:



1: <connectionStrings>
2: <add name="AcSqlConnString"
3: connectionString="server=[YourSqlServerName];database=AcAspNetDB; Integrated Security=SSPI;"
4: providerName="System.Data.SqlClient"
5: />
6: </connectionStrings>





With the connection string set up, now we need to specify the membership and role providers. In this article I'm using the ASP.NET SQL membership and role providers, so I need to add the following to the
web.config

file, within the
<system.web>
node:




1: <!-- membership provider -->
2: <membership defaultProvider="AcAspNetSqlMembershipProvider">
3: <providers>
4: <add name="AcAspNetSqlMembershipProvider"
5: type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
6: connectionStringName="AcSqlConnString"
7: enablePasswordRetrieval="false"
8: enablePasswordReset="true"
9: requiresQuestionAndAnswer="false"
10: applicationName="/"
11: requiresUniqueEmail="false"
12: passwordFormat="Hashed"
13: maxInvalidPasswordAttempts="5"
14: minRequiredPasswordLength="1"
15: minRequiredNonalphanumericCharacters="0"
16: passwordAttemptWindow="10"
17: passwordStrengthRegularExpression=""
18: />
19: </providers>
20: </membership>
21:
22: <!-- role provider -->
23: <roleManager enabled="true" defaultProvider="AcAspNetSqlRoleProvider">
24: <providers>
25: <add name="AcAspNetSqlRoleProvider"
26: type="System.Web.Security.SqlRoleProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
27: connectionStringName="AcSqlConnString"
28: applicationName="/"
29: />
30: </providers>
31: </roleManager>






There are a few things you should take note of from the above code (marked in bold). First, note the name and connectionString attribute for the providers. When you install the .NET Framework 2.0, default connection strings and providers are specified in the machine.config file (located in the %windir%\Microsoft.NET\Framework\v2.0.5027\CONFIG). You want to make sure you use unique names here and not the names that Microsoft has included as the default names in the machine.config file. If you elect to reuse their names, you'll need to explicitly remove each one by name (via the <remove /> node) or clear all predefined connection strings and providers (via the <clear /> node). To make it easy, I specified unique names, as indicated in bold.

With everything configured, launch the ASP.NET 2.0 Web administration site from within Visual Studio 2005: Website -> ASP.NET Configuration. When the site loads, the first order of business is to switch it from Integrated Authentication to Forms Authentication. To do this, select the Security link and then select the Select Authentication Type link in the Users container. If it isn't selected already, make sure From The Internet (aka: Forms Authentication) is selected and click Done.

Create A User

Next, we need to add a user that we'll later use for testing. Select Security again and then select Create User. I'm going to create a new user with the User Name of Shaji and Password of password. Note I don't have to enter a strong password because of some of the settings I changed in the membership provider in the code above. The E-mail address isn't important, so I'll just enter shajimji@gmail.com and click Create User.
Finally, let's make sure the markup in our web.config file is correct for our membership and role provider. To do this, select the Provider tab and then select Select a Different Provider For Each Feature (Advanced). You should see the membership and role provider that we specified in our web.config. Selecting the Test link for either should confirm they are successfully talking to the database.

At this point, we now have our ASP.NET 2.0 user and role database store configured. More importantly we should have a good template web.config containing the connection string, membership provider and role provider settings that we can copy from when modifying the web.config files for our SharePoint sites. Now we need some Web applications to configure!


Creating Two Web Applications, One For Each Authentication Mechanism



We need some sites to configure for authentication right? I mean, that's the point of the article right?

Creating the http://extranet IIS Web site
First step is to create a new Web application just like you would any other time. From SharePoint's Central Administration Web site, select the Application Management tab, then Create or Extend Web Application and then Create a New Web Application. I'm guessing if you're reading this article, you know how to create a new Web application from here… so I'll spare the details, but I want to point out is that I specified the following:

  • Set the Description as SharePoint – Extranet 80
  • Set the Port to 80
  • Set the Host Header to extranet
  • Picked NTLM as the Authentication Provider
  • Specified Anonymous Access to No

After creating the Web application, I then created a new site collection in the Web application naming the site Acme and picking the Publishing Portal site template. If you're having problems and want to see exactly what I selected, you can view Figure 3 displaying the Create New Web Application page or Figure 4 displaying the Create Site Collection page.

At this point we now have a site, configured for Windows Authentication, named ACME at http://extranet. This is the site our content owners will use to authenticate using their Active Directory corporate accounts in order to add, edit, and manage the content on our Publishing site. Make sure everything is working by browsing to the http://extranet Acme site. You should see the Welcome control and the Site Actions menu in the upper right-hand corner of the page. Assuming everything is working, we have now satisfied the first goal listed in the introduction above!

Creating the http://internet IIS Web site


Now we need to extend our Web application to another IIS Web site. This is the site our anonymous, or Internet users, will use to access the site. This site will need to be available to anonymous users as well as provide a mechanism for them to authenticate against, via Forms Authentication, in order to access restricted areas of the site (such as a member's only section). To extend the Acme Web application to another IIS Web site, from SharePoint's Central Administration, select the Application Management tab, then Create or Extend Web Application and then Extend an Existing Web Application. Again, I'll spare you from the details and highlight only a few important points on this page:


  • Make sure you select the Web application you want to extend… in our case we want SharePoint – Extranet 80. Use the Web Application selector at the top of the page to
  • pick the correct application.
  • Set the Description as SharePoint – Internet 80
  • Set the Port to 80
  • Set the Host Header to internet
  • Picked NTLM as the Authentication Provider
  • Specified Anonymous Access to No
  • Set the Load Balanced URL Zone to Internet



We'll enable anonymous access later.


Again, if you are having problems, you can see exactly what I selected from Figure 5. Now we have a site that we can configure for our Internet users to access anonymously and also login via Forms Authentication. However, before we do that, there are a few configuration tasks we have to do.

Configure The Web Applications To Communicate With The ASP.NET 2.0 Forms Authentication Data Store



Once you have a Web application created that will host a site, you will need to change its authentication provider to not use Windows Authentication but instead use Forms Authentication as well as configure the site so it can communicate with our user and role data store… the AcAspNetDb we created earlier. To do this, we'll use the connection string, membership provider, and role provider we created and already tested in our utility Web site's web.config file.

Configure http://extranet & http://internet
First, we'll modify the two IIS Web sites (http://extranet and http://internet) web.config files to include the connection string, membership provider, and role provider information so they can both communicate with our user and role store. It's obvious why the http://internet site would need these changes, but why make them to the http://extranet site when we're going to use it for Forms authentication? If we didn't, it would be somewhat difficult and inconvenient (but not impossible) when we needed to grant any special permissions in the Acme Web application to one of the users or roles in our data store. This way, one of our content owners can authenticate using his/her Active Directory credentials and still grant a user who will authenticate via Forms Authentication access within the site.

Open the web.config file for the http://extranet Web site, found in the following directory (if you let SharePoint specify the Web site root directory... otherwise, retrieve it from your specified path): c:\Inetpub\wwwroot\wss\VirtualDirectories\extranet80. Add the <connectionStrings> node, listed above, just after the closing </SharePoint> tag and opening <system.web> tag. Then add the membership and role provider markup, listed above, just after the opening <system.web> tag and save your changes. Do the same thing for the web.config for the http://internet Web site, found here: c:\Inetpub\wwwroot\wss\VirtualDirectories\internet80.


Configure SharePoint Central Administration

Now both Web applications are configured to communicate with the data store. There's one last step we have to do… we need to add the same information to the SharePoint's Central Administration Web site's web.config file. Why? We need to make sure the Central Administration Web site can communicate with the data store in case we want to do any security management of the users and roles in the data store such as configuring policies for the Web application. Repeat the steps above for the Central Administration's web.config which should be found here: c:\Inetpub\wwwroot\wss\VirtualDirectories\[#####]. You need to make one small change… change the defaultProvider attribute on the <roleManager> node to AspNetWindowsTokenRoleProvider. This is necessary because Central Administration still uses Windows Authentication for the role provider. The <roleManager> node for the Central Administration's web.config should look like this:


1: <!-- role provider -->
2: <roleManager enabled="true" defaultProvider="AspNetWindowsTokenRoleProvider">
3: <providers>
4: <add name="AcAspNetSqlRoleProvider"
5: type="System.Web.Security.SqlRoleProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
6: connectionStringName="AcSqlConnString"
7: applicationName="/"
8: />
9: </providers>
10: </roleManager>



Now we're finally ready to configure the http://internet site for Forms Authentication!

Enabling Forms Authentication On One Web Application




Flipping the switch to Forms Authentication is very simple… it's just all the prep work that's the complicated part. Browse to SharePoint's Central Administration Web site, select the Application Management tab, and then select Authentication Providers. First, ensure you are working with the correct Web application by checking the selector in the upper right-hand corner of the Authentication Providers page (as shown in Figure 6). Once you're on the correct Web application, select the Internet zone link (as shown in Figure 6).





Figure 6 – Authentication Providers page

Note that even though we've selected the http://extranet Web application, we are really modifying the http://internet IIS Web site because that's the one mapped to the Internet zone.


On the Edit Authentication page, we are going to change the Internet zone for the http://extranet Web application to the following settings:


  • Authentication Type: Forms
  • Enable Anonymous Access: checked
  • Membership Provider Name: AcAspNetSqlMembershipProvider
  • Role Manager Name: AcAspNetSqlRoleProvider



Notice that the names of the Membership Provider Name and Role Manager Name are the names of the providers we entered in the web.config's. Now you see why we had some pre-configuration work to do before we actually made the switch. Refer to Figure 7 to see all settings I selected on the Edit Authentication page.

We now have two different ways for users to get to our Acme Web application:

  • Via http://extranet, authenticating using Windows Authentication (using their Active Directory credentials)
  • Via http://internet, anonymously or authenticating using Forms Authentication



Ah.. but we're not quite finished. Even though the http://internet Web site is now configured to allow anonymous users, the Acme Web application has not been set to grant permission for anonymous users to browse the site. You can prove this by trying to browse to http://internet. You'll immediately get redirected to the default SharePoint Forms Authentication Sign In page, as shown in Figure 8.




Figure 8 – SharePoint's default Forms Authentication Sign In Page


Let's prove that the Forms Authentication is actually working with our data store. First we need to add our user to the site. To do this, browse to the http://extranet Web site, select Site Actions, then Site Settings, then People And Groups. Select the New button to add a user to the site. On the Add Users: Shaji page, enter the username of the user we created previously: Shaji. Then click the Check Names icon (little icon with a blue check just below the Users/Groups input box… or press [CTRL]+[K]). In the Give Permission section, select Add Users To A SharePoint Group and select Shaji Visitors [Read] and finally click OK. We've now granted our user access to the site.

To test, open a new browser window and browse to http://internet. You should immediately get sent to the SharePoint Sign In page. Enter the account's credentials (Shaji/password) and click Sign In. You'll then get signed in and redirected back to the homepage of the site. You can see you're logged in because you can now see the Welcome control in the upper right-hand corner of the site. Notice how you can't see the Site Actions menu? That's because we only have the rights assigned to Visitors, which means we can't do anything to the site but browse it.

Last step… let's open the site up for anonymous users…


Enabling Anonymous Access


In order for anonymous users to have access to the Acme Web application and browse the site, we need to turn anonymous access on. In our case though, we only want to turn anonymous access on for the external (or http://internet) site. Before we do this, we should create a new account in our ASP.NET 2.0 database that we can use as an administrative account to make changes to our external site. First, create a new account using the same process in the Setting Up ASP.NET 2.0 Forms Authentication User & Role Data Store: Create A User section above. I'm going to create this account with the following credentials:

  • Username: FbaAdmninistrator
  • Password: password



Next, we need to grant this user ownership-level rights to our http://internet site. WSS v3 introduces a new capability where we can specify a user to have full control over a site via Web Application policies. These policies trump any permission setting within the site itself. We'll use this to set a policy to grant the FbaAdministrator full control over our http://internet site. Browse to Central Administration, select the Application Management tab, then Policy for Web application under the Application Security section. Make sure you've selected the correct Web Application from the selector in the upper-right corner of the page (in our case, we want to select http://extranet). Next, select Add Users from the toolbar. On the Add Users page, select the Internet zone (because this is the zone we specified for our http://internet Web Application) and click Next. Finally, enter the user FbaAdministrator in the Choose Users step, select Full Control in the Choose Permissions step, and click Finish. Now you can login to the http://internet site and have full control over the site, just like the site owners have.

Now we can setup anonymous access for our http://internet site. To do this, browse to the http://internet Web site, login using the FbaAdministrator account we just created and configured, select Site Actions, then Site Settings, then Modify All Site Settings. On the Site Settings page, select Advanced Permissions. On the Permissions: Acme page, select Settings, and then select Anonymous Access (see Figure 9). On the Change Anonymous Access Settings: Acme page, select Entire Web Site and click Ok.






To test, open a new browser window and browse to http://internet. You should go straight to the Web site as an anonymous user! You can tell you aren't signed in because there's a Sign In link in the upper right-hand corner of the site where the Welcome control usually is. We have now satisfied the second goal listed in the introduction above!


Configuring A Section Of the Site For Authenticated Users Only


Our last goal was to configure a section of the site so that users must be authenticated to have access to that section's, or site's, content. To do this, we'll have to go back into our site as through the http://extranet. Because the site is now set up for anonymous access, you won't automatically be signed in, so you'll have to click the Sign In link in the upper right-hand corner. Because we created the site using the Publishing Portal template, there's a subsite named Press Releases in our site collection.

Let's make it so this site requires the user to login. Select Site Actions and then Manage Content and Structure. On the Site Content and Structure page, select Press Releases from the left-hand navigation tree and then select Advanced Permissions (see Figure 10).





Figure 10 – Press Releases Advanced Permissions

Next, we'll break the permission inheritance with the parent site and then remove anonymous access to the Press Releases site. First, select Actions and then Edit Permissions. You'll be prompted to accept your changes… select OK. Next, Select Settings, then Anonymous Access, then on the Change Anonymous Access Settings page, select Nothing and click OK.

Now let's test it… open a new browser window and navigate to http://internet. Notice how the Press Releases section isn't on the horizontal navigation (see Figure 11)? Now sign in using the Sign In link in the upper right-hand corner and watch how the Press Releases section now appears since we're authenticated (see Figure 12)! We have now satisfied the third goal listed in the introduction above!



Figure 11 – Unauthenticated User With Press Releases Site Hidden

Figure 12 – Authenticated User With Press Releases Site Visible


Conclusion

In this article I have demonstrated how you can create a Publishing Site in MOSS 2007 and configure it for two types of authentication and at the same time allow anonymous users to browse the site. So where would you go from here? Some possible next steps would include creating a self-registration system for users to create their own accounts and have these accounts automatically registered on the site under a specific role so no additional management action is required by the site owners.

Friday, May 16, 2008

Authentication and Authorization

At their core, the membership and role providers exist to provide authentication and authorization services to our applications. Authentication is the process verifying the identity of a user. The membership provider can create new users and passwords in a database, and validate a user’s identity using the saved information. The membership provider uses a Microsoft SQL Server database. There is also a membership provider available for Active Directory, but this article will concentrate on the SQL Server membership provider.

ASP.NET 2.0 provides login controls we can drop on web forms to perform authentication with no code required. The controls talk directly to the membership provider. ASP.NET 2.0 also offers controls to support the ongoing maintenance of users, including changing passwords and resetting passwords. All of these controls build on top of features of the membership providers.

Once we know who a user is, we can find out what we will allow the user to do – this is authorization. The role providers in 2.0 allow us to create roles, and map users into the roles. For example, you might build an application with two roles: Administrators and RegisteredUsers. Given a username, the role manager can tell us to which roles a user belongs. Areas of a web application, or specific operations, can be restricted to exact roles.

Of course, your application might have special needs. Perhaps your database is not Microsoft SQL Server. Fortunately, Microsoft implemented both membership and role management using an extensible provider model. The provider model is the keystone of the membership and role services, so we will begin our tour of the functionality by covering what a provider does.

Providers

The provider model in ASP.NET 2.0 provides extensibility points for developers to plug their own implementation of a feature into the runtime. Both the membership and role features in ASP.NET 2.0 follow the provider pattern by specifying an interface, or contract. If you build your component to fulfill the contract a provider defines, you can plug your code into the ASP.NET runtime and replace or extend the existing providers. The provider model in ASP.NET 2.0 includes an infrastructure for the configuration and initialization of providers.

The provider model begins with the abstract class ProviderBase. ProviderBase exists to enforce the contract that all providers need public Name and Description properties, as well as a public Initialize method. Inheriting from ProviderBase are the MembershipProvider and RoleProvider abstract classes. These classes add additional properties and methods to define the interface for their specific areas of functionality.

As an example, the MembershipProvider requires a membership class to implement a ValidateUser method. The default membership provider in 2.0, the SqlMembershipProvider, implements this method by executing a stored procedure in a SQL Server database. If you want to write your own provider to use an XML file as a data store for membership information, you’ll have to write the code for ValidateUser to verify a user’s password against information kept in the XML file.

The beauty of the provider model is this: higher-level application services can build upon a provider and not need to know the details of what happens behind the interface. A good example is the ASP.NET 2.0 membership controls, which include a Login control, a CreateUser control, a LoginStatus control, and more. All of these controls program against the MembershipProvider contract. At some point, the login control will need to invoke the ValidateUser method on the configured provider. The login control doesn’t care if the call travels to a SQL Server database or an XML file. All the login control cares about is passing in a username and a password and receiving a true or false value in return.

The MembershipProvider

The purpose of the MembershipProvider is to provide a layer of indirection between membership controls, like the LoginControl, and the data store containing membership information. The indirection means we can use any data store (SQL Server, Oracle, XML, Web Service, Active Directory), as long as we have a provider to hide the details behind the public methods and properties of a concrete class. As we mentioned earlier, ASP.NET 2.0 includes providers for SQL Server and Active Directory.

A successful .NET installation will configure the SqlMembershipProvider class from the System.Web assembly as the default membership provider. You can verify the default by looking to the machine.config file, which applies settings to all the managed applications on a computer. The machine.config file is found in the config directory where the framework is installed, typically \Windows\Microsoft.NET\Framework\v2.0.xxxx.


<membership>
<providers>
<add
name="AspNetSqlMembershipProvider"
type="System.Web.Security.SqlMembershipProvider, ..."
connectionStringName="LocalSqlServer"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="true"
applicationName="/"
requiresUniqueEmail="false"
passwordFormat="Hashed"
maxInvalidPasswordAttempts="5"
minRequiredPasswordLength="7"
minRequiredNonalphanumericCharacters="1"
passwordAttemptWindow="10"
passwordStrengthRegularExpression=""
/>
</providers>
</membership>



Configuring The Membership Provider

The membership section of machine.config contains a variety of knobs we can tweak – many of these tweaks involve user password management.


To take advantage of membership features, all you’ll need to do is use the new Login web controls in ASP.NET 2.0. The CreateUser control provides all the UI and implementation needed to fetch a user’s name, password, email, and security question and answer. The PasswordRecovery control allows a user to retrieve an existing or reset password via email. To all the Login controls in action, take a look the Securing Your Application” ASP.NET tutorials.


The passwordFormat property specifies how the provider will store passwords, and will impact a number of other membership features. The SqlMembershipProvider supports three formats: Hashed (the default and most secure format), Encrypted, and Clear. The hashed format passes a user’s plaintext password and a random salt value through a one-way hash algorithm before storing the password. You cannot retrieve a hashed password. To validate a password, the provider has to salt and hash the entered password and compare the two hash values (for more information on hashing passwords, see Pass The Salt). The provider can also store encrypted passwords (which can be decrypted and retrieved), or store passwords in the clear (which is not recommended).

The enablePasswordRetrieval option determines if the provider will return a user’s password with the GetPassword method. If the password format is set to Hashed, passwords are not retrievable. If the provider keeps passwords in an encrypted or clear text format, you could email a user’s forgotten password to them, but think of the security implications first. A more secure option in the event of a lost password is to reset the user’s password to a new value and email the new password (make sure to enforce unique email addresses with requiresUniqueEmail).

The enablePasswordReset property controls the ResetPassword API. ResetPassword will assign a new, generated password to a user. The PasswordRecovery control can automatically email the new password to a user. It a good idea to set the requiresQuestionAndAnswer property to true to prevent a malicious user from resetting someone else’s password, A value of true means the user has to provide the answer to a security question before resetting their password. The question and answer text is will be required by the CreateUser control when a adding a new user.

A number of properties control the password strength a provider will allow. The minRequiredPasswordLength and minRequiredNonalphanumericCharacters prevent users from choosing a password like “abc”. If you have additional requirements, you can use the passwordStrengthRegularExpression property to force the password to pass a regular expression test. Note: a password generated by ResetPassword will always meet the required password length and required number of non-alphanumeric characters, but may not meet pass the regular expression test.

The SqlMembershipProvider offers a number of features not shown in the configuration above. For instance, the maxInvalidPasswordAttempts and passwordAttemptWindow properties work together to prevent a malicious user from using brute force techniques to break into a user account. Too many bad passwords will lock out a user account and prevent the account from logging in until the account is unlocked with the UnlockUser method.

Membership and SQL Server

Other properties in the membership section control how SqlMembershipProvider interacts with SQL Server. By default, the machine.config file configures membership and roles to work with a SQL Server Express database file in the App_Data directory. Looking back at the configuration excerpt above, we see the connectionStringName property is “LocalSqlServer”. If you locate the connectionStrings section of machine.config you’ll find the following:


<add name="LocalSqlServer"
connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true"
providerName="System.Data.SqlClient" />



You can always override the default setting and point all providers using LocalSqlServer to a remote database, or a non-Express database on the local machine. The first step would be to use the ASP.NET Sql Server Registration Tool (aspnet_regsql.exe) to create a new database. You can find the tool in the .NET framework installation directory (WINDOWS\Microsoft.NET\Framework\2.0.xxxx). If you launch the tool without command line parameters, the tool will launch a wizard to walk through the setup for a new database. The default database name is aspnetdb.

One you’ve configured a database for the provider to use, you can modify the web.config file for your application to redefine the LocalSqlServer connection string to point to the new database.



<connectionStrings>
<remove name="LocalSqlServer"/>
<add name="LocalSqlServer"
connectionString="server=.;database=aspnetdb;integrated security=sspi;"/>
</connectionStrings>




Alternatively, you can define a new connection string and modify the connectionStringName property of a provider to use the new connection string.

You can test your settings with the ASP.NET Configuration tool (under the Website menu is Visual Studio). On the Provider tab, choose “Select a different provider for each feature”, and you’ll arrive at the following page that allows you to “test” each provider’s connectivity. The administration tool also contains pages to manage security settings, create users, and more.

Another important property to set in the membership configuration is the applicationName property. The applicationName allows one database to support multiple web applications. If you have two web applications and want both apps to share the same user base, give both applications the same applicationName and point them to the same aspnetdb database. If you want both applications to use the same database but not share users, give each application a unique applicationName property.

Using The Membership Provider

If you want to interact directly with the Membership API, one approach is to use the Membership class from System.Web.Security. The Membership class contains only static members and properties, but these static members map to properties and methods on the MembershipProvider, and the component will forward calls to the configured provider when appropriate. Here is an example using hard coded values for a user's attributes.

string username = "SwedishChef";

string password = "bj#kbj1k";

string email = @"swede@mailinator.com";

string question = "The greatest band ever?";

string answer = "ABBA";

bool isApproved = true;

MembershipCreateStatus status;

Membership.CreateUser(

username, password, email,

question, answer, isApproved,

out status);

if(status == MembershipCreateStatus.Success)

{

// party!

}



An even easier interface to the membership provider is to use the ASP.NET 2.0 Login controls: Login, LoginView, PasswordRecovery, LoginStatus, LoginName, CreateUserWizard, and ChangePassword. The Login control, for example, will ultimately call the ValidateUser method of the current membership provider when a user enter their username and password and clicks the Login button. There is no need to write any code if the built-in controls provide all the functionality you need. All of the controls allow customization various levels of customization through styles and templates. You can find the controls in the Visual Studio toolbox under the “Login” category.

Thursday, May 15, 2008

Command Line Administration for SharePoint

Think about how people interact with Windows or Microsoft Office. Some users are avid mousers, using the pointer to navigate menus and toolbars to perform common tasks. Others are comfortable
with the keyboard, quickly executing familiar keystrokes and shortcuts. For any given task, there is almost always several ways to get it done.
The fact is, a graphical interface can be easy to use, but it can be equally cumbersome for tasks that require you to do the same thing repeatedly. Some things are easier to do with the keyboard. If you do any SharePoint® administration, you've probably experienced what it's like to be bogged down in a graphical interface. But SharePoint actually offers a more powerful way to get things done.
The primary interface for managing Windows® SharePoint Services (WSS) and Microsoft® Office SharePoint Server 2007 (MOSS) is the GUI-based SharePoint Central Administration. But SharePoint also includes a command-line tool for more powerful administration. This tool, STSADM.exe, provides all the functionality of SharePoint Central Administration, but with the command-line flexibility many administrators desire. In this article, I will give you a crash course in using STSADM to manage WSS and MOSS. I'll also give you some tips on how to configure your environment and discuss some common STSADM commands. I will even show you some advanced STSADM commands that can make you look like a hero-if the need to use them ever arises

Getting Started
If you haven't stumbled upon STSADM, it could be because it is somewhat buried. In Windows SharePoint Services 2.0, it's in c:\program files\common files\microsoft shared\web server extensions\60\bin by default. The default location in version 3.0 is c:\program files\common files\microsoft shared\web server extensions\12\bin.
To simplify access to this tool, I use two different approaches. First, I simply add that directory to my PATH environment variable. This way I can use STSADM wherever I am in the file system. This, however, is not always an option. My second approach is to create a shortcut to CMD.EXE and set STSADM's location as the initial directory. Why not just point a shortcut directly to STSADM? This doesn't work since STSADM is not interactive. As a result, if you do point a shortcut directly to STSADM, you will be presented with a quick display of its usage and then it will be gone.
When you run STSADM, you need to be a member of the local Administrators group on the Web server, and you need to execute the app locally. This means you cannot use STSADM to remotely administer a SharePoint server.
To see what operations you can perform with STSADM, type stsadm.exe -help in a command prompt. Be sure to check this list after you apply updates and hotfixes to SharePoint since new operations may be added. There is also a handy guide to stsadm.exe operations available at go.microsoft.com/fwlink/?LinkId=77516.

STSADM Basics
Let's start by looking at some of the commands you might use to tweak your existing SharePoint installation. You can use STSADM to add functionality to SharePoint and to modify configuration settings.
STSADM uses the -o parameter followed by the operation you want to perform. Just typing STSADM -operationname will not work. If, for example, you want to add site templates to your installation, you can use the following command:


Stsadm -o addtemplate -filename -title <title> -description

Or, if you want to add a Web Part Package, you can use this command:

Stsadm -o addwppack -filename

For details on usage for any operation, simply pass the operation with no parameters and STSADM will tell you what it expects for input. STSADM -help operationname will also give you usage info.
When managing templates, you can use the enumtemplates operation to see which templates have been added and deletetemplate to remove any that are installed. Similarly, there are commands to work with Web Part packages. You can use the enumwppacks operation to list the Web Part packages installed on each virtual server or Web application, and deletewppack will let you remove any that have been added.
STSADM also has two operations that deal with SharePoint settings: setproperty and getproperty. Executing either with no parameters will give you a list of the properties you can view or manipulate. Like STSADM itself, this list changes with updates and hotfixes. Nevertheless, there are a few properties that are more useful than others. Figure 1 lists some of the properties you may want set after you get SharePoint installed, including the most common properties I hear SharePoint administrators ask about


Property Function
Alerts-enabled Turns alerts on or off for your virtual server or Web application.
Alerts-limited Specifies whether users are restricted to setting a certain number of alerts on the virtual server or Web application.
Alerts-maximum If alert limits are set, this is the maximum number of alerts that a user can set.
Days-to-show-new-icon This sets how long the "New" icon appears next to items added to the Web site, like announcement posts, for instance.
Job-immediate-alerts Specifies how often SharePoint looks for immediate alerts to send out. The default for SharePoint 2.0 is five minutes. You can adjust that interval here. Decreasing the time will increase load on your Web and database servers, so keep an eye on it if you change this property.
Job-daily-alerts Specifies what time the daily alerts are sent out. SharePoint 2.0 defaults to "between 22:00 and 06:00." If you have users who are not in the same time zone as the server, you may want to adjust this property.
Job-weekly-alerts You probably see the pattern here. This sets the schedule for weekly alerts

Figure 1

Let's take a quick look at using one of these properties. The following command will have SharePoint send out immediate alerts every 10 minutes:

Stsadm -o setproperty -pn job-immediate-alerts -pv "Every 10 minutes"

Notice I used -pn and -pv instead of -propertyname and -propertyvalue. These are acceptable shortcuts for those times when you don't want to type the entire word. Also note that all the examples and commands I have discussed in this section will work for both versions 2.0 and 3.0 of Windows SharePoint Services.

Daily Administration

Day-to-day SharePoint administration is pretty easy. For most SharePoint administrators, the bulk of daily tasks consist of working with users and sites. STSADM has several operations to streamline these tasks.
I'll start with sites and webs. For purposes of consistency, I will use "site" to refer to site collections and "web" to refer to subsites (also known as subwebs). Some of the terminology is tricky, but if you stay consistent with what STSADM uses, it will be easier to find the command you need.
If you run a large SharePoint installation, you probably spend a lot of time creating new sites for users. I know I find myself repeatedly doing this. Creating new sites can be done quite easily in SharePoint Central Administration. But since I perform this task so often, I find it faster to use STSADM to get the job done.
I use the createsite operation. This is quite simple and takes the following parameters:

  • url
  • ownerlogin
  • owneremail
  • ownername
  • lcid
  • sitetemplate
  • title
  • description
  • quota
You can bring these up at the command prompt by typing stsadm -help createsite (see Figure 2). Of these nine parameters, the only mandatory fields are URL, ownerlogin, and owneremail.



If you have sites that you create on a routine basis, you can go a step further in streamlining the process by writing a wrapper script around STSADM to automate the task. For instance, to automate the creation of personal sites, you can save the following to a text file named createpersonalsite.cmd

stsadm -o createsite -url http://localhost/users/%1 -ownerlogin contoso\%1
-owneremail %1@contoso.com -sitetemplate usersite.stp
-title "Personal site for %1" -description "Personal site for %1" -quota "500 MB"




Figure 2
Createsite Parameters

And then to create a site for the user jsmith, you could simply execute the following:

createpersonalsite.cmd jsmith

By scripting site creation, you save yourself a lot of typing and can make sure all your newly created sites are consistent. The operation createweb provides the same functionality at the web level.
In Windows SharePoint Services 2.0, the only easy way to get an exhaustive list of the site collections on a particular virtual server is to use STSADM. Enumsites lists in XML format all of the site collections on a specific virtual server or Web application. This can be coupled with a Data View Web Part to easily view a list of site collections. (See the sidebar "Working with a Data View Web Part" for more information.)
STSADM provides a deletesite operation for, as you can guess, removing sites. All you need to do is provide the URL. Optionally, you can pass it -deleteadaccounts to have the accounts deleted in Active Directory®. When working with webs you would use the deleteweb operation.
You can also add, delete, and enumerate the users of a site or web. The associated operations are adduser, deleteuser, and enumusers. These operations are handy if users need to be added to a site in bulk, or if you need to maintain a list of users who have access to a site for auditing purposes.
When working with webs you have access to an additional operation, renameweb, that lets you change the name and URL of a web. For example, to rename a web from "oldname" to "coolnewname," use the following:

Stsadm -o renameweb -url http://localhost/oldname -newname coolnewname

This can be a life saver when project names change or business units are realigned. In Windows SharePoint Services 2.0, this is a big issue, as the only way to migrate webs is with SMIGRATE.exe, which does not maintain any user-related settings like membership or alerts. With Windows SharePoint Services 3.0, this is less of an issue, as STSADM can back up and restore webs and sites.

Backing Up and Restoring
One of the best uses for STSADM is backing up and restoring sites and webs. For small to medium-sized installations, this functionality can be the cornerstone of a disaster recovery plan. The backup operation is self-explanatory and very easy to use. Simply tell STSADM which site to back up and where to write the backup file, like this:

Stsadm -o backup -url http://localhost -filename site.bak

This operation dumps the entire site collection to the file site.bak. It includes all site content, such as webs, document versions, lists, and users. It does not back up any site definitions or changes you've made at the file system level of your servers.
While the backup operation is important, it does have a few snags to keep an eye on. If the site is large enough, the Content Database may be locked during the backup process. This may prevent users from accessing any sites in that database until the backup operation is finished. This issue has been mitigated with service packs, but it is still something to keep an eye on as your sites grow. STSADM also uses the server's temp directory when doing backups and restores, so monitor your drive space.

Working with a Data View Web Part
You can couple the enumsites command with a Data View Web Part to create an easy way to view a list of site collections. Let's see how.
First, create a scheduled task that runs:

stsadm –o enumsites –url http://localhost>c:\inetpub\wwwroot\excludedsite\sites.xml


Make sure the XML file is being written out to a directory that is published with IIS, but not managed by SharePoint. Then use Microsoft FrontPage® (or the FrontPage successor, Microsoft Office SharePoint Designer 2007) to add a Data View Web Part to a Web Part page and point it at the URL of the XML file.
The Data View Web Part provides functionality like sorting, filtering, and grouping. You can also make the URL field a link to take you directly to the site. If you would like a list of webs instead, the operation enumsubwebs provides an XML output of the subwebs in a site collection or web


Finally, keep in mind that while STSADM backups work well for small to medium sites, the functionality does not scale particularly well. For very large sites (several gigabytes or more), the backup and restore processes can slow down quite a bit.
Restoring a site is equally simple. STSADM -o restore takes a file created by STSADM -o backup and writes it to a site in SharePoint. You have a lot of flexibility with this command: you can restore a site back to its original location (if, for instance, the site was erroneously deleted), you can restore it as a different site on the same virtual server (perhaps if you want to test a process on a site without the risk of destroying data), or you can restore the site to a completely different server or virtual server.
Restoring to a different site or server makes it a bit easier to do individual document recovery. If you have a site backed up and a user needs a document restored, you do not need to restore the entire site. That would sacrifice all changes made to the site since the backup was stored. Instead, you can just restore the site to a different URL, grab the documents, and save them back to the original site.
In Windows SharePoint Services 2.0, STSADM has one fairly serious limitation. When backing up, it can only deal with sites, not with webs. Administrators made their discontent known and Microsoft responded. In Windows SharePoint Services 3.0, the backup and restore operations can now handle webs. It also adds two new commands: import and export.
To export a web, use the following simple command:

Stsadm -o export -url http://localhost/web -filename backup.dat

Export has handy options, including the -versions switch. This allows you to decide how large your backup files will be by restricting which file versions will be backed up.
To import a web back to the server, use the following command:

Stsadm -o import -url http://localhost/web2 -filename backup.dat

If your site is large enough, the backup file might be in multiple parts. In this case, point STSADM -o import to the first file and it will automatically grab the subsequent files

Expert Operations
Now that you are comfortable with STSADM, I want to show you a couple of operations you can use to get out of a bind. The first is a newly added operation called migrateuser. Version 2.0 does not sync itself with Active Directory. If an account is renamed, it can no longer log in to SharePoint. In the past, there was also no way to migrate user access from one domain user to another. Before Windows SharePoint Services 2.0 Service Pack 2 (SP2), you had to remove the user from every web and manually add the new account.
SP2 introduced a new API and STSADM takes advantage of it. If the account jsmith is renamed to jjones, you can use the following command:

Stsadm -o migrateuser -oldlogin domain\jsmith -newlogin domain\jjones -ignoresidhistory

Since you're not actually migrating accounts, you can ignore Windows security ID (SID) history. Note that this command does not require a URL. It makes the change throughout the content databases, without regard to sites or webs.
Another operation that can get you out of a bind is unextendvs. If you do not want SharePoint to render a virtual server or Web application, you unextend it. Normally, you would do this from the SharePoint Configuration Analyzer. However, in a Web farm, SharePoint Configuration Analyzer requires that your servers are all at the same patch level. It is possible for a server to be out of sync with the rest of the farm and, therefore, it will not get the unextend option in SharePoint Configuration Analyzer. Using STSADM, though, the following command will unextend your virtual server:

Stsadm -o unextendvs -url http://localhost

Once the server is no longer in the Web farm, you can perform the maintenance you need.
On the subject of Web farms, for ease of administration, you may want all of your servers to have SharePoint Configuration Analyzer on the same port. The port is randomly generated when SharePoint is installed, but STSADM includes an operation to change the port to one you specify:

Stsadm -o setadminport -port 1026

This makes all the necessary database changes, it makes the IIS changes, and it adjusts the shortcut to SharePoint Configuration Analyzer in Administrative Tools.


Windows SharePoint Services is a powerful solution and it requires powerful administration. STSADM provides a way to accomplish SharePoint administration, including the automation of configuration and common day-to-day tasks. In fact, sometimes it is the only way to get the job done.

Wednesday, May 14, 2008

SharePoint impersonation: Id and Ego

Description:
We probably should have called the title of this article ‘SharePoint and impersonation’ or some other rather predictable title like that, because that’s the topic of this article. But there’s no fun in that, so instead we decided to call it ‘Id, Ego and Superego’, concepts which are borrowed from the famous psychologist Sigmund Freud and applied very loosely to SharePoint.

Freud used the terms Id, Ego and Superego to describe the human character. The ‘Id’ (pronounced as ‘it’) describes the lower, more animalistic parts of our character. The ‘Ego’ part of the human character describes the way most of us act in everyday life, the Ego part is a compromise between needs, lust, morals and realism. Finally, the ‘Superego’ represents higher values, ethics and morale. Maybe you could say that the Superego is what most of us would like to be like.

Sometimes when creating web parts you might want to do things which ordinary users are not allowed to, for instance, when you want to use the SharePoint administration object model to display information about SharePoint. If you’re feeling lucky you could solve the problem by making everybody administrator but chances are you won’t be nominated to win the Microsoft Trustworthy computing award this year – again.

Another solution would be to change the identity to an account with more privileges during the web part life cycle, do the stuff which demand additional privileges, and change the identity back again to the original context. In this article we will show you three different approaches to impersonation and we’ll use the concepts of Id, Ego and Superego to give those approaches a name.


SharePoint OM code sample requiring administrator privileges

To be able to demonstrate that the impersonation code actually works you’ll need to create an account with Reader rights for SharePoint. We use a small code sample which uses the SharePoint object model to display the URL and server id of the current virtual server. You need to be an administrator to be able to do this. If you create a web part you could override the RenderWebPart method like this:

protected override void RenderWebPart(HtmlTextWriter output)

{

string strValue = String.Empty;

try

{

SPSite objSite = SPControl.GetContextSite(Context);

SPGlobalAdmin objAdmin = new SPGlobalAdmin();

SPVirtualServer objServer = objAdmin.OpenVirtualServer(new Uri(objSite.Url));

objServer.CatchAccessDeniedException = false;

strValue += "url: " + objServer.Url + " virtual server id: " + objServer.VirtualServerId;

}

catch (Exception err)

{

strValue = "Error in wp: " + err.Message;

}

output.Write(strValue);

}


The code itself is unimportant, the only thing that is important is that it requires administrator privileges. This makes it an excellent test to see if the impersonation works. By the way, the CatchAccessDeniedException property of the SPSite object is used to specify that access denied errors aren’t handled which prevents authentication dialog boxes from popping up.

If you open a browser by rightclicking it, choosing the ‘Run as’ option and log in with a previously created reader account you’ll see that access will be denied (and if you didn’t set the CatchAccessDeniedException to false you will have plenty of opportunity to notice this).


Policy files

If you want to be able to execute all code samples it’s easiest if you set the trust level in the SharePoint web.config file to ‘Full’, like so:



We like to work with our own custom policy files. If you’re using custom policy files as well and if you want to be able to execute the ‘Id’ and ‘Ego’ approaches make sure the following permissions are present in your policy file:


class="AspNetHostingPermission"

version="1"

Level="Minimal"

/>

version="1"

Unrestricted="true"/>

class="SecurityPermission"

version="1"

Flags="Execution,UnmanagedCode,ControlPrincipal,ControlAppDomain,

ControlEvidence"

/>

version="1"

Connections="True"

/>

version="1"

ObjectModel="True"

UnsafeSaveOnGet="True"

/>


As for the Superego approach, as it turned out, to be able to execute this scenario we found we needed so much permissions that we chose the easy route and used full trust instead.


Ego

In this approach we’ll use a Win32 API call to the LogonUser function to impersonate another user account. The first thing you need to do is import two dll’s, advapi.dll and kernel32.dll. To do this add the following code to your web part class:


[DllImport("advapi32.dll", SetLastError=true)]

static extern bool LogonUser(

string principal,

string authority,

string password,

LogonTypes logonType,

LogonProviders logonProvider,

out IntPtr token);

[DllImport("kernel32.dll", SetLastError=true)]

static extern bool CloseHandle(IntPtr handle);


Advapi32.dll contains the LogonUser function which attempts to log on a user to a local computer. The most important arguments which need to be passed to this function are a username, domain and password. The function returns a boolean value indicating if the logon was successful. A handle is passed (by reference), the handle is very important because it can be used to create a new windows identity.

After that you’ll also need a couple of enumerations which can be used as arguments for the LogonUser function as well. Add the following code to your web part class:

enum LogonTypes : uint

{

Interactive = 2,

Network,

Batch,

Service,

NetworkCleartext = 8,

NewCredentials

}

enum LogonProviders : uint

{

Default = 0, // default for platform (use this!)

WinNT35, // sends smoke signals to authority

WinNT40, // uses NTLM

WinNT50 // negotiates Kerb or NTLM

}

By the way, it’s better to use the Network logon type instead of the Interactive type because of performance reasons and the elimination of the call to DuplicateToken (MS KB article 306158, see http://support.microsoft.com/?kbid=306158 ).

Kernel32.dll contains the CloseHandle function which closes an open object handle. This function is used to close the handle which was the result of the LogonUser call.

The following code shows how to override the RenderWebPart method to impersonate users via the LogonUser API call:


protected override void RenderWebPart(HtmlTextWriter output)

{

string strValue = String.Empty;

try

{

WindowsImpersonationContext objUserContext;

IntPtr objToken;

WindowsIdentity objOrgIdentity;

WindowsIdentity objIdentity;

bool blnReturn = LogonUser(@"myadministrator", "mydomain", "myadminpassword",

LogonTypes.Interactive,

LogonProviders.Default,

out objToken);

if ( blnReturn )

{

objOrgIdentity = WindowsIdentity.GetCurrent();

objIdentity = new WindowsIdentity(objToken);

objUserContext = objIdentity.Impersonate();

SPSite objSite = SPControl.GetContextSite(Context);

SPGlobalAdmin objAdmin = new SPGlobalAdmin();

SPVirtualServer objServer = objAdmin.OpenVirtualServer(new

Uri(objSite.Url));

objServer.CatchAccessDeniedException = false;

strValue += "url: " + objServer.Url + " virtual server id: " +

objServer.VirtualServerId + "

";

strValue += "Identity name after impersonation: " + " " +

objIdentity.Name + "
";

objUserContext.Undo();

strValue += "Indentity name when impersonation is undone: " +

objOrgIdentity.Name;

CloseHandle(objToken);

}

else

{

strValue = "Logon failed!";

}

}

catch (Exception err)

{

strValue = "Error in wp: " + err.Message;

}

output.Write(strValue);

}


So, to sum up, this is the Ego approach, where the current user context is replaced with a new context.


Id

One of the complaints we hear about the Ego approach is that user credentials are stored in the code which is, and rightfully so, considered unsafe. Well, you shouldn’t store passwords in plain text in code, it’s as simple as that, but there are ways to avoid this. You could save the password in a config file after encrypting it using DPAPI. Another nice solution would be to use SharePoint Single Sign On (SSO) and store the credentials in the credential mapping database.

There is another solution, using credential-less impersonation, which we’ve named the ‘Id’ approach. This approach is explained in detail in a very informative article called ‘Secure SharePoint Code Using Credential-less Impersonation’ by Todd Bleeker ( http://sharepointadvisor.com/doc/16238 ).

Basically, a call is made to the Win32 API RevertToSelf function which terminates the impersonation of a client application. SharePoint uses Internet Information Server 6 (IIS) and IIS 6 uses application pool identities as the context in which worker processes run. It’s possible to revert back from a current user context (which is itself an impersonated identity) to the original identity, which is the application pool identity.

The credentials of the application pool identity are stored safely in the IIS metabase. SharePoint requires the application pool identity to be a local administrator and administrator of the SharePoint content database. So, by dumping the current context and reverting to the application pool’s security context it’s possible to do stuff that requires an extensive set of privileges while avoiding storing credentials in code.

To make this possible you’ll need to import the Advapi32.dll. Add the following code to your web part class definition:


[DllImport("advapi32.dll")]

static extern bool RevertToSelf();



As you can see, the RevertToSelf function isn’t hard to use. The following code shows how to override the RenderWebPart method to revert back to the application pool’s security context:

protected override void RenderWebPart(HtmlTextWriter output)

{

string strValue = String.Empty;

try

{

WindowsIdentity objOriginalUser = WindowsIdentity.GetCurrent();

RevertToSelf();

SPSite objSite = SPControl.GetContextSite(Context);

SPGlobalAdmin objAdmin = new SPGlobalAdmin();

SPVirtualServer objServer = objAdmin.OpenVirtualServer(new

Uri(objSite.Url));

objServer.CatchAccessDeniedException = false;

strValue += "url: " + objServer.Url + " virtual server id: " +

objServer.VirtualServerId + "

";

strValue += "application pool identity name: " +

WindowsIdentity.GetCurrent().Name + "
";

WindowsImpersonationContext objContext =

objOriginalUser.Impersonate();

strValue += "original user name: " +

WindowsIdentity.GetCurrent().Name;

}

catch (Exception err)

{

strValue = "Error in wp: " + err.Message;

}

output.Write(strValue);

}


In the Id approach the current user context is reverted back to the underlying original security context. The big difference with the Ego approach is you don’t need to find a way or place to store credentials of a superuser. Also check out the following link: http://mindsharpblogs.com/todd/archive/2005/05/03/467.aspx , this small article explains a way to do impersonation code in a way that requires a smaller set of security privileges.