In a previous
post I shared some thoughts regarding changes to authentication
providers in SharePoint 2010. As I worked through the issue of
removing Claims/FBA and reverting to NTLM I discovered a number of
issues that manifested themselves in strange ways. The first
problem I encountered was the inability for a Farm account to make
changes to the Authentication Providers settings in Central
Administration. The System Account couldn't even view the dialog -
each attempt resulted in a 403 error. This was bad news as a lot of
things happen behind the scenes when changing authentication
settings in this dialog - not the least of which is propagation of
changes to all the web servers. This meant I would have to undo all
of the Claims settings manually and repeat them on each server. Not
my idea of a fun afternoon.
I began by changing the authentication provider for my content web
applications back to Classic mode using Powershell:
$webApp = Get-SPWebApplication http://site
$webApp.UseClaimsAuthentication = 0;
$webApp.Update()
$webApp.ProvisionGlobally()
Next, I removed the highlighted membership provider from inclusion
in the people picker in all web applications, including Central
Administration:
<PeoplePickerWildcards>
<clear />
<add key="AspNetSqlMembershipProvider" value="%"
/>
<add key="MyCustomMembershipProvider" value="%"
/>
</PeoplePickerWildcards>
The next part of the process involves the removal of role and
membership provider information, along with any supporting
connection strings, from the various web.config files. This has to
be done for the Central Administration web app, the Security Token
Service web app, and all content web apps that use Claims on each
web server. The process is a bit different for each type of web
application, so it's not just a simple matter of find and
delete.
Starting with the Security Token Service, locate the web.config
file in the C:\Program Files\Common Files\Microsoft Shared\Web
Server Extensions\14\WebServices\SecurityToken directory and remove
all the entries added to enable Claims in the first place.
Typically, these are located after the <system.net> entries
in a new <system.web> node:
<system.web>
<membership defaultProvider="i">
<providers>
<add name="i"
type="Microsoft.SharePoint.Administration.Claims.SPClaimsAuthMembershipProvider,
Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral,
PublicKeyToken=71e9bce111e9429c" />
<add name="MyCustomMembershipProvider"
connectionStringName="MyDBConnection" passwordAttemptWindow="2"
maxInvalidPasswordAttempts="100" enablePasswordRetrieval="true"
enablePasswordReset="true" requiresQuestionAndAnswer="false"
applicationName="/" minRequiredNonalphanumericCharacters="0"
minRequiredPasswordLength="8" requiresUniqueEmail="true"
passwordFormat="Clear" description="Stores and Retrieves membership
data from SQL Server"
type="System.Web.Security.SqlMembershipProvider, System.Web,
Version=2.0.3600.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a" />
</providers>
</membership>
<roleManager defaultProvider="c" enabled="true"
cacheRolesInCookie="false">
<providers>
<add name="c"
type="Microsoft.SharePoint.Administration.Claims.SPClaimsAuthRoleProvider,
Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral,
PublicKeyToken=71e9bce111e9429c" />
<add name="MyCustomRoleProvider"
connectionStringName="MyDBConnection" applicationName="/"
description="Stores and retrieves roles from SQL Server"
type="System.Web.Security.SqlRoleProvider, System.Web,
Version=2.0.3600.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a" />
</providers>
</roleManager>
</system.web>
Be sure to also remove any connection strings:
<connectionStrings>
<add name="MyDBConnection" connectionString="user
id=[User/Password];Persist Security Info=False;Initial
Catalog=[Database Name];Data Source=[Server]"
providerName="System.Data.SqlClient" />
</connectionStrings>
In the Central Administration web application config, the
membership and role provider nodes have a slightly different syntax
from the Security Token and content web applications but this
doesn't have any bearing on the removal of Claims from the
environment. Replace them with the out of the box configuration
settings (basically an empty set of nodes), so this:
<roleManager
defaultProvider="AspNetWindowsTokenRoleProvider" enabled="true"
cacheRolesInCookie="false">
<providers>
<add name="MyCustomRoleProvider"
connectionStringName="MyDBConnection" applicationName="/"
description="Stores and retrieves roles from SQL Server"
type="System.Web.Security.SqlRoleProvider, System.Web,
Version=2.0.3600.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a" />
</providers>
</roleManager>
<membership defaultProvider=" MyCustomMembershipProvider
">
<providers>
<add name="MyCustomMembershipProvider"
connectionStringName="MyDBConnection" passwordAttemptWindow="2"
maxInvalidPasswordAttempts="100" enablePasswordRetrieval="true"
enablePasswordReset="true" requiresQuestionAndAnswer="false"
applicationName="/" minRequiredNonalphanumericCharacters="0"
minRequiredPasswordLength="8" requiresUniqueEmail="true"
passwordFormat="Clear" description="Stores and Retrieves membership
data from SQL Server"
type="System.Web.Security.SqlMembershipProvider, System.Web,
Version=2.0.3600.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a" />
</providers>
</membership>
Becomes this:
<roleManager>
<providers>
</providers>
</roleManager>
<membership>
<providers>
</providers>
</membership>
We can now move on to the content web applications and remove the
membership and role information, along with any connection strings,
from those web.config files. Remember that this has to be done on
every web server in the farm (including any application servers
which have the Microsoft SharePoint Foundation Web Application
role). Remove the following nodes in their entirety (if you wish,
you may replace the <roleManager> and <membership>
sections with empty nodes as was done with Central
Administration):
<membership defaultProvider="i">
<providers>
<add name="i"
type="Microsoft.SharePoint.Administration.Claims.SPClaimsAuthMembershipProvider,
Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral,
PublicKeyToken=71e9bce111e9429c" />
<add name="MyCustomMembershipProvider"
connectionStringName="MyDBConnection" passwordAttemptWindow="2"
maxInvalidPasswordAttempts="100" enablePasswordRetrieval="true"
enablePasswordReset="true" requiresQuestionAndAnswer="false"
applicationName="/" minRequiredNonalphanumericCharacters="0"
minRequiredPasswordLength="8" requiresUniqueEmail="true"
passwordFormat="Clear" description="Stores and Retrieves membership
data from SQL Server"
type="System.Web.Security.SqlMembershipProvider, System.Web,
Version=2.0.3600.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a" />
</providers>
</membership>
<roleManager defaultProvider="c" enabled="true"
cacheRolesInCookie="false">
<providers>
<add name="c"
type="Microsoft.SharePoint.Administration.Claims.SPClaimsAuthRoleProvider,
Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral,
PublicKeyToken=71e9bce111e9429c" />
<add name="MyCustomRoleProvider"
connectionStringName="MyDBConnection" applicationName="/"
description="Stores and retrieves roles from SQL Server"
type="System.Web.Security.SqlRoleProvider, System.Web,
Version=2.0.3600.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a" />
</providers>
</roleManager>
<connectionStrings>
<add name="MyDBConnection" connectionString="user
id=[User/Password];Persist Security Info=False;Initial
Catalog=LearningCounts;Data Source=[Server]"
providerName="System.Data.SqlClient" />
</connectionStrings>
After the membership and role settings have been removed, the
manner in which users are prompted for authentication must be
changed. In Claims mode, a login form is presented to the user but
in Classic mode we want the NTLM prompt instead. This setting is
controlled by the following lines in the content web application
web.config files:
<authentication mode="Forms">
<forms loginUrl="/_login/default.aspx" />
</authentication>
Changing it to the following will re-enable the NTLM prompt:
<authentication mode="Windows" />
The next step is to remove all Claims accounts from the web
application in User Policy settings and replace them with NTLM
accounts:

At this point, Classic authentication should be working on all web
applications. As mentioned
previously, it will be necessary to remove and replace user
accounts in SharePoint groups on each site collection and it may
also be necessary to change entries in the Site Owners group. After
getting this far, it would appear that Claims has been disabled -
users should get an NTLM prompt when attempting to navigate to site
pages and be able to login successfully. Alas, our work is not yet
done. While the Claims authentication settings have been changed,
there are a number of artifacts left behind in the web.config files
which enable the system to process Claims identities. These
artifacts won't prevent users from logging in using NTLM but they
will cause various other issues, one of which is the strange
behavior that occurs when attempting to login as a different user
in the same browser session.
SharePoint provides a link in the Personal Actions menu entitled
"Sign in as a different user". This link points to
"/_layouts/closeconnection.aspx" with a query string argument of
"?loginasanotheruser=true" and a second argument which points back
to the referring page. If everything is working properly, the
current user will be logged out and an NTLM prompt displayed for
new user credentials. If things aren't in such good shape, the user
will be redirected to the "/_layouts/accessdenied.aspx" page and
receive a generic SharePoint error, which is exactly what happened
to me. Digging through the ULS log files, I found the matching
correlation ID which revealed the underlying error:
System.ArgumentException:
Exception of type 'System.ArgumentException' was thrown. Parameter
name: identity
at
Microsoft.SharePoint.Administration.Claims.SPClaimProviderManager.GetUserIdentifierEncodedClaim(IIdentity
identity)
at
Microsoft.SharePoint.Administration.Claims.SPClaimExtensionMethods.GetDisplayName(IClaimsIdentity
claimsIdentity)
at
Microsoft.SharePoint.ApplicationPages.AccessDeniedPage.OnLoad(EventArgs
e)
at
System.Web.UI.Control.LoadRecursive()
at
System.Web.UI.Page.ProcessRequestMain(Boolean
includeStagesBeforeAsyncPoint, Boolean
includeStagesAfterAsyncPoint) 26b85aba-6b2a-4b96-93de-91aa18db98d3
The error indicates that the system is still trying to process user
identities in Claims mode instead of Classic mode. To rectify this
situation, it is necessary to remove all the Claims-related entries
in the content web application web.config files. Your mileage may
vary, but a compare on a clean non-Claims config file and the ones
I had been working with revealed the following entries which needed
to be cleaned up:
<httpModules>
<add
name="FederatedAuthentication"
type="Microsoft.SharePoint.IdentityModel.SPFederationAuthenticationModule,
Microsoft.SharePoint.IdentityModel, Version=14.0.0.0,
Culture=neutral, PublicKeyToken=71e9bce111e9429c"
/>
<add
name="SessionAuthentication"
type="Microsoft.SharePoint.IdentityModel.SPSessionAuthenticationModule,
Microsoft.SharePoint.IdentityModel, Version=14.0.0.0,
Culture=neutral, PublicKeyToken=71e9bce111e9429c"
/>
<add
name="SPWindowsClaimsAuthentication"
type="Microsoft.SharePoint.IdentityModel.SPWindowsClaimsAuthenticationHttpModule,
Microsoft.SharePoint.IdentityModel, Version=14.0.0.0,
Culture=neutral, PublicKeyToken=71e9bce111e9429c"
/>
</httpModules>
<assemblies>
<add
assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral,
PublicKeyToken=71e9bce111e9429c" />
<add
assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
<add
assembly="Microsoft.Web.CommandUI, Version=14.0.0.0,
Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
<add
assembly="Microsoft.SharePoint.Search, Version=14.0.0.0,
Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
<add
assembly="Microsoft.Office.Access.Server.UI, Version=14.0.0.0,
Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
<add
assembly="Microsoft.SharePoint.Publishing, Version=14.0.0.0,
Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
<add
assembly="Microsoft.Office.Server.Search, Version=14.0.0.0,
Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
<add
assembly="Microsoft.IdentityModel, Version=3.5.0.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35"
/>
<add
assembly="Microsoft.SharePoint.IdentityModel, Version=14.0.0.0,
Culture=neutral, PublicKeyToken=71e9bce111e9429c"
/>
</assemblies>
<modules
runAllManagedModulesForAllRequests="true">
<remove
name="AnonymousIdentification" />
<remove
name="FileAuthorization" />
<remove name="Profile"
/>
<remove
name="WebDAVModule" />
<remove name="Session"
/>
<add
name="SPRequestModule" preCondition="integratedMode"
type="Microsoft.SharePoint.ApplicationRuntime.SPRequestModule,
Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral,
PublicKeyToken=71e9bce111e9429c" />
<add name="ScriptModule"
preCondition="integratedMode"
type="System.Web.Handlers.ScriptModule, System.Web.Extensions,
Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
/>
<add
name="SharePoint14Module" preCondition="integratedMode"
/>
<add
name="StateServiceModule"
type="Microsoft.Office.Server.Administration.StateModule,
Microsoft.Office.Server, Version=14.0.0.0, Culture=neutral,
PublicKeyToken=71e9bce111e9429c" />
<add
name="RSRedirectModule"
type="Microsoft.ReportingServices.SharePoint.Soap.RSRedirectModule,
RSSharePointSoapProxy, Version=10.0.0.0, Culture=neutral,
PublicKeyToken=89845dcd8080cc91" />
<add
name="PublishingHttpModule"
type="Microsoft.SharePoint.Publishing.PublishingHttpModule,
Microsoft.SharePoint.Publishing, Version=14.0.0.0, Culture=neutral,
PublicKeyToken=71e9bce111e9429c" />
<add
name="FederatedAuthentication"
type="Microsoft.SharePoint.IdentityModel.SPFederationAuthenticationModule,
Microsoft.SharePoint.IdentityModel, Version=14.0.0.0,
Culture=neutral, PublicKeyToken=71e9bce111e9429c"
/>
<add
name="SessionAuthentication"
type="Microsoft.SharePoint.IdentityModel.SPSessionAuthenticationModule,
Microsoft.SharePoint.IdentityModel, Version=14.0.0.0,
Culture=neutral, PublicKeyToken=71e9bce111e9429c"
/>
<add
name="SPWindowsClaimsAuthentication"
type="Microsoft.SharePoint.IdentityModel.SPWindowsClaimsAuthenticationHttpModule,
Microsoft.SharePoint.IdentityModel, Version=14.0.0.0,
Culture=neutral, PublicKeyToken=71e9bce111e9429c"
/>
</modules>
<microsoft.identityModel>
<service
saveBootstrapTokens="true">
<audienceUris
/>
<issuerNameRegistry
type="Microsoft.SharePoint.IdentityModel.SPPassiveIssuerNameRegistry,
Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral,
PublicKeyToken=71e9bce111e9429c" />
<securityTokenHandlers>
<clear />
<add
type="Microsoft.IdentityModel.Tokens.X509SecurityTokenHandler,
Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
<add
type="Microsoft.SharePoint.IdentityModel.SPSaml11SecurityTokenHandler,
Microsoft.SharePoint.IdentityModel, Version=14.0.0.0,
Culture=neutral, PublicKeyToken=71e9bce111e9429c">
<samlSecurityTokenRequirement>
<nameClaimType
value="http://schemas.microsoft.com/sharepoint/2009/08/claims/userid"
/>
</samlSecurityTokenRequirement>
</add>
<add
type="Microsoft.SharePoint.IdentityModel.SPTokenCache,
Microsoft.SharePoint.IdentityModel, Version=14.0.0.0,
Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
</securityTokenHandlers>
<federatedAuthentication>
<wsFederation
passiveRedirectEnabled="false" issuer="https://none"
realm="https://none" />
<cookieHandler
mode="Custom" path="/">
<customCookieHandler
type="Microsoft.SharePoint.IdentityModel.SPChunkedCookieHandler,
Microsoft.SharePoint.IdentityModel, Version=14.0.0.0,
Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
</cookieHandler>
</federatedAuthentication>
</service>
</microsoft.identityModel>
Once these are removed, all Claims settings should be gone and
Classic mode fully restored. Note that the above samples are all
based on the AspNetMembershipProvider using SQL as the data source.
Use of LDAP or other identity providers may result in a different
set of configuration entries. Alter the procedure as necessary for
your environment, remembering to compare a pre-Claims config file
(if you have one) with a post-Claims file to identify all of the
changes. Don't forget to check the Authorization settings in the
IIS manager as well just to be sure everything is working
properly.
This article was orginally posted on binarywave
by MVP,
Eric Shupps
Stay tuned for more SharePoint content by joining our community or by
following us on twitter or
facebook.