My SharePoint 2007 Custom Membership Provider Adventure
Sometime last year I wanted to set up a SharePoint 2007 website for my family members to exchange information. That being said, I was using a custom membership provider, and I ran into a few issues while I was setting things up. I had kept detailed notes while I was configuring my server and troubleshooting the problems that I encountered, and with that in mind, I thought that I would share my experiences. ;-]
Getting Started
Specifying My Environment
My web server is only an older 32-bit Windows Server 2008 computer, so I couldn’t install SharePoint 2010 (which is 64-bit only) and I had to install SharePoint 2007. Taking that into account, there were a few additional considerations that I had for my environment:
- I wanted to use Forms-Based Authentication (FBA). Even though I run my own active directory domain, I avoid giving out physical accounts if I don’t have to, so FBA seemed like a great idea.
- I didn’t want to use the built-in ASP.NET membership and roles provider. This is for two reasons:
- I was already using the built-in ASP.NET membership provider on other websites, and I didn’t feel like researching whether I should share the membership database between SharePoint and my other websites, or if I should set up unique membership databases.
- If you’ve been reading my previous blogs and you think that I’d be content with using a built-in provider, then you haven’t been paying attention. Usually I find myself wanting to do things the hard way, and other times I simply want to write code, but either way I decided to use the sample read-only XML membership and role providers that I documented in the following article:
- I decided that I could use FBA over HTTP, and therefore I didn’t worry about setting up SSL. (I run my own certificate server, so I could have issued myself a certificate and given the root CA certificate to everyone; but this wasn’t necessary, so I didn’t bother with it.)
Researching My Scenario
With my specific considerations in mind, I took a look at the following article to get started:
- HTTP://www.simple-talk.com/dotnet/windows-forms/configuring-forms-authentication-in-sharepoint-2007/
That being said, I did not use the following articles, even though they are related to my scenario and they looked interesting:
- HTTP://msdn.microsoft.com/en-us/library/bb975136.aspx
- HTTP://msdn.microsoft.com/en-us/library/bb975135.aspx
Creating the SharePoint Website
Here are the brief details on how I created my SharePoint website:
- I followed the steps in the following walkthrough in order to create and register the read-only XML membership and role providers with IIS 7:
- I created the following physical paths for my website:
- Website root folder: C:InetpubSharePointSitewwwroot
- Application data folder: C:InetpubSharePointSitewwwrootApp_Data
- I created the following user/role XML file for my website:
- I created an XML file in the location: C:InetpubSharePointSitewwwrootApp_DataMyUsers.XML
- I added the following XML to the file:
Users User UserNameAlice/UserName PasswordP@ssw0rd/Password EMailalice@contoso.com/EMail RolesAdmins/Roles /User User UserNameBob/UserName PasswordP@ssw0rd/Password EMailbob@contoso.com/EMail RolesAuthors/Roles /User /Users
- I opened the Internet Information Services (IIS) Manager and created a new website; I used the C:InetpubSharePointSitewwwroot folder for the home directory.
- I opened SharePoint 3.0 Central Administration to convert my website into a SharePoint 2007 site:
- I clicked the Application Management tab, then clicked Create or extend Web Application, and then clicked Create a new Web Application:
- In my case I chose Use an existing IIS web site because I had already created the website that I wanted to use.
- I chose Create new application pool, I used “Network Service” for the identification, and then I specified all of the requisite database information.
- When that completed, I clicked the Application Management tab, and then clicked Create site collection:
- I specified all options, and I used a valid Active Directory account as the administrator for now.
- Once the site was created, I modified the web.config file for the website and the SharePoint Central Administration web.config file. (See the following notes for the details.) Note: The SharePoint Central Administration website needs to know the information about your membership provider in order to add administrators.
- After that, I clicked the Application Management tab, and then clicked Authentication Providers:
- I verified that I was using the correct “Web Application” in the drop-down menu.
- I clicked on the Default zone.
- I set the Authentication Type to Forms.
- I specified the appropriate Membership provider name and Role manager name.
- When that completed, I needed to restart IIS before continuing. (NOTE: I used “iisreset” from a command line.)
- After IIS had restarted, I clicked the Application Management tab, and then clicked Site collection administrators:
- I added a user (like Alice or Bob) from the membership provider.
- I clicked the Application Management tab, then clicked Create or extend Web Application, and then clicked Create a new Web Application:
web.Config Entries
There are a few additions that you have to make to your website’s web.config file, as well as the SharePoint Central Administration web.config file for SharePoint 2007:
- Here’s the XML that you need to add to the
system.websection of your website’s web.config; in my example that file would be located at “C:InetpubSharePointSitewwwrootweb.config“:!-- added on 05/31/2011 -- membership defaultProvider="ReadOnlyXmlMembershipProvider" providers add name="ReadOnlyXmlMembershipProvider" type="ReadOnlyXmlMembershipProvider, ReadOnlyXmlMembershipProvider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=426f62526f636b73" description="Read-only XML membership provider" xmlFileName="~/App_Data/MyUsers.xml" / /providers /membership roleManager enabled="true" defaultProvider="ReadOnlyXmlRoleProvider" providers add name="ReadOnlyXmlRoleProvider" type="ReadOnlyXmlRoleProvider, ReadOnlyXmlRoleProvider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=426f62526f636b73" description="Read-only XML role provider" xmlFileName="~/App_Data/MyUsers.xml" / /providers /roleManager !--/added on 05/31/2011 --
- Here’s the XML that you need to add to the
system.websection of your SharePoint Central Administration web.config file; on my server that file is located at “C:inetpubwwwrootwssVirtualDirectories6087web.config“:!-- added on 05/31/2011 -- membership defaultProvider="ReadOnlyXmlMembershipProvider" providers add name="ReadOnlyXmlMembershipProvider" type="ReadOnlyXmlMembershipProvider, ReadOnlyXmlMembershipProvider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=426f62526f636b73" description="Read-only XML membership provider" xmlFileName="~/App_Data/MyUsers.xml" / /providers /membership !--/added on 05/31/2011 --
IMPORTANT!!!
SharePoint Central Administration needs to be able to find the MyUsers.xml file, so I created an App_Data folder under physical path of the SharePoint Central Administration website, and I added a symbolic link in that folder that pointed to the physical MyUsers.xml file. Here’s how I did that:
- I opened a command prompt.
- I changed directory to the path where my SharePoint global web.config file was located; for example:
cd C:inetpubwwwrootwssVirtualDirectories6087
- I created a symbolic link to the physical path of the XML file; for example:
mklink MyUsers.xml C:InetpubSharePointSitewwwrootApp_DataMyUsers.xml
- I closed the command prompt.
Note: I could have copied the XML file, but I preferred to use the symbolic link instead of having to manage two copies of the file.
Optional People Picker Settings
If you were installing a membership provider that can perform lookups, you could add an additional entry to your SharePoint Central Administration web.config file:
PeoplePickerWildcards clear / add key="AspNetSqlMembershipProvider" value="%" / !-- added on 05/31/2011 -- add key="ReadOnlyXmlMembershipProvider" value="%" / !--/added on 05/31/2011 -- /PeoplePickerWildcards
Problems that I Encountered
Okay – I admit that I everything that I did so far was probably making things harder that they needed to be, but I love a good challenge. ;-]
That being said, I ran into some problems that I thought would be worth mentioning, just in case someone else ran into them.
HTTP 403 Errors
When browsing to my SharePoint website, I received several HTTP 403 errors. I used Process Monitor to troubleshoot the problem, and I discovered that IUSR could not access the “bin” folder in my website. (I’m still not quite sure why it was trying.) To resolve these errors, I used the following steps:
- I opened a command prompt.
- I changed directory to the SharePoint website’s path; for example:
cd C:InetpubSharePointSitewwwroot
- I changed permissions for the “bin” folder; for example:
icacls bin /grant IIS_IUSRS:r
- I closed the command prompt.
In my situation the problem was for IUSR, but if you are using a different anonymous identity or your application pool is running as a unique identity then it might be a different user. In any case, Process Monitor will let you know who needs permissions.
Later I discovered the following blog post by John Powell:
In that blog, John suggests adding the following permissions for the “bin” folder:
icacls bin /grant users:r
I’m not sure if that’s necessary, but it’s worth pointing out.
HTTP 404.8 Errors
When browsing to my SharePoint website, I received several HTTP 404.8 errors. Those errors mean that the built-in IIS 7 Request Filtering feature was blocking something, so I did the following:
- I opened my website’s web.config file; on my server that file was located at “C:InetpubSharePointSitewwwrootweb.config“:
- I added the following XML before the closing
/configurationtag:system.webServer !-- added on 05/31/2011 -- security requestFiltering hiddenSegments clear / add segment="web.config" / add segment="bin" / add segment="App_code" / add segment="App_GlobalResources" / add segment="App_LocalResources" / add segment="App_WebReferences" / add segment="App_Data" / add segment="App_Browsers" / /hiddenSegments /requestFiltering /security !--/added on 05/31/2011 -- /system.webServer
- I saved and closed the web.config file.
Note: This removes all of the hidden segments from the global IIS 7 Request Filtering settings, which may be overkill. I have a lot of custom global request filtering settings, and I didn’t want to go through each individual setting to see which setting was blocking files that I needed, so I used settings for my website that cleared the inherited request filtering settings and added the default settings.
Annoying Message: “The web site wants to run the following add-on: ‘Name ActiveX Control’”
When browsing to my SharePoint website, the information bar in Internet Explorer kept prompting me with the following message:
The Web site wants to run the following add-on: ‘Name ActiveX Control’ from ‘Microsoft Corporation’. If you trust the Web site and the add-on and want to allow it to run, click here…
This message was highly frustrating, so I did some digging around the Internet and discovered that I could hack the INIT.JS file for SharePoint to suppress this message. Here’s how I did that:
- I opened my server’s INIT.JS file; on my server that file was located at “C:Program FilesCommon Filesmicrosoft sharedWeb Server Extensions12TEMPLATELAYOUTS1033INIT.JS“.
- I located the
ProcessImn()andProcessImnMarkers()functions, and I remarked out the contents. Here’s what this looked like when I was done:function ProcessImn() { // if (EnsureIMNControl() IMNControlObj.PresenceEnabled) // { // imnElems=document.getElementsByName("imnmark"); // imnElemsCount=imnElems.length; // ProcessImnMarkers(); // } } function ProcessImnMarkers() { // for (i=0;iimnMarkerBatchSize;++i) // { // if (imnCount==imnElemsCount) // return; // IMNRC(imnElems[imnCount].sip,imnElems[imnCount]); // imnCount++; // } // setTimeout("ProcessImnMarkers()",imnMarkerBatchDelay); }
- I saved and closed the INIT.JS file.
I should note that this solution is unsupported; and a few months I hacked my INIT.JS file, Microsoft published the following Knowledge Base article with a couple of different methods:
That being said, I like my solution better. ;-]