Hiding Default Authentication Providers and Bypassing the Multi-Authentication Provider Selection Page in SharePoint 2010

Summary:  Learn how to hide the default authentication provider and bypass the multi-authentication provider selection page in Microsoft SharePoint 2010.

Applies to: Business Connectivity Services | Open XML | SharePoint Designer 2010 | SharePoint Foundation 2010 | SharePoint Online | SharePoint Server 2010 | Visual Studio

Provided by:  Steve Peschka, Microsoft Corporation

Contents

  • Overview of Hiding the Default Authentication Provider and Bypassing the Multi-Authentication Provider Selection Page in SharePoint 2010

  • Hiding the Default Authentication Providers in SharePoint 2010

  • Bypassing the Multi-Authentication Provider Selection Page in SharePoint 2010

  • Conclusion

  • Additional Resources

Overview of Hiding the Default Authentication Provider and Bypassing the Multi-Authentication Provider Selection Page in SharePoint 2010

Using a single zone for multiple authentication providers is a scenario that you see occurring more frequently in Microsoft SharePoint 2010. One of the reasons that you might want to use a single zone for multiple authentication providers is because you want to use some kind of claims authentication—like forms-based authentication or Security Assertion Markup Language (SAML)—but you also want to add Windows claims so that the zone can be indexed by the SharePoint 2010 crawler. The problem with this approach is two-fold:

  1. When users are added to a site (or any operation is performed that invokes the People Picker), they see Active Directory directory service users in the People Picker results, and users for the claims authentication providers that they are using.

  2. Users see a login selection page, where they have to select either Windows authentication or some other kind of authentication.

You can write a custom login selection page to solve the second problem. You can resolve the first problem by hiding Active Directory users from being displayed in the People Picker search results. These solutions are discussed in detail in the following sections.

Hiding the Default Authentication Providers in SharePoint 2010

To hide Active Directory users from being displayed in the People Picker search results, you set the IsVisible property in the SPClaimProviderDefinitions class to false for the Active Directory provider. After you have done that, the Active Directory provider no longer appears when you use the People Picker.

Note

To use the new IsVisible property in the SPClaimProviderDefinitions class, you must install the SharePoint 2010 June cumulative update.

The following is a Windows PowerShell cmdlet snippet that shows how to set the IsVisible property to false.

$cpm = Get-SPClaimProviderManager
$ad = get-spclaimprovider -identity "AD"
$ad.IsVisible = $false
$cpm.Update()

Note

The Windows PowerShell command Get-SPClaimProvider actually returns a SPClaimProviderDefinition object. The identity AD is used because that is the internal name of the Active Directory provider.

In my limited testing, I did not have to do an IISRESET after making this change; I could immediately use the People Picker and Active Directory no longer showed in the list of authentication providers in the left pane of the People Picker. Conversely, when I changed it back, the Active Directory showed up again immediately without an IISRESET.

At this time, the biggest limitation with this is that it does not appear that you can enforce this setting on a per-zone basis, which would be ideal. If I find out otherwise at a later date, I will update my blog post titled Hiding Default Authentication Providers in SharePoint 2010.

Bypassing the Multi-Authentication Provider Selection Page in SharePoint 2010

I recently needed to bypass the authentication provider selection page that you see when you enable multiple authentication providers on a single zone in SharePoint 2010. The scenario that I had was a fairly simple one. But the methodology I use can be extended to support much more complex scenarios. In my case, I had Windows authentication and forms-based authentication enabled on a zone. However, I wanted to redirect users to use forms-based authentication for this particular scenario.

Accomplishing this was relatively straightforward by following these steps:

  1. Make a backup copy of the default.aspx file in the C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\IDENTITYMODEL\LOGIN folder.

  2. In Microsoft Visual Studio, create a Windows Class Library project.

  3. Add references to System.Web, Microsoft.SharePoint.dll, and Microsoft.SharePoint.IdentityModel.dll. The identity model assembly is in the global assembly cache. Therefore, I had to get a copy and place it in the root of my drive to add my references. For a suggestion about how to find and copy the assembly, see the blog post Writing A Custom Forms Login Page for SharePoint 2010 Part 1.

  4. Strong name the assembly that you are creating, because you will place it the global assembly cache later.

  5. Add a new ASPX page to your project. I find the easiest way to do this is to copy a page from an existing ASP.NET web application project; if you do this, you can copy the .aspx, .aspx.cs, and .aspx.designer.cs files all at the same time. Remember, in this case we want a file that is named "default.aspx", and it will be easier if there is no code written in it yet and there is minimal markup in the page.

  6. In the code-behind file (.aspx.cs file), change the namespace to match the namespace of your current project.

  7. Change the class so that it inherits from Microsoft.SharePoint.IdentityModel.Pages.MultiLogonPage.

  8. Override the OnLoad event. When a user hits a site that has multiple authentication providers enabled, the user is first sent to the /_login/default.aspx page (the page described in step 1). On that page, a user selects which authentication provider to use and then the user is redirected to the correct page to authenticate. In this scenario, I have said earlier that I always want users to authenticate with forms-based authentication. Therefore, I want to send them to /_forms/default.aspx. If you step through a typical login process, the following steps occur:

    1. You are first redirected to /_login/default.aspx.

    2. You make your authentication provider selection.

    3. You post back to /_login/default.aspx.

    4. You are redirected to the correct login page.

    So, in this case, I looked to see whether my login page was being posted back. If it is not, I know that no selection was made yet for the authentication provider. I just enumerate all the query string values and then append them to /_forms/default.aspx and redirect the user there. The following is the code example.

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
    
        try
        {
            // If this is not a post back, the user has not yet selected which
            // authentication provider they want to use.
            // In this case, we want to always refer the user to log in by using forms-based authentication.
            if (!this.IsPostBack)
            {
                // Grab all the query string parameters.
                System.Text.StringBuilder qp = new System.Text.StringBuilder(2048);
    
                foreach (string key in this.Request.QueryString.Keys)
                {
                    qp.Append(key + "=" + this.Request.QueryString[key] + "&");
                }
    
                // Redirect to the forms-based authentication login page.
                this.Response.Redirect("/_forms/default.aspx?" + qp.ToString());
            }
        }
        catch (Exception ex) 
        {
            Debug.WriteLine(ex.Message);
        }
    }
    
  9. Compile the application so that you can get the strong name for it and add it to the markup for default.aspx.

  10. Copy the following markup into default.aspx; you just have to change the class from which the page inherits (in this example, "MultiAuthLoginPage._Default,MultiAuthLoginPage, Version=1.0.0.0, Culture=neutral, PublicKeyToken=907bf41ebba93579"). Note that all I did was copy it from /_login/default.aspx and replace the Inherits value with my custom class information.

    <%@ Page Language="C#" CodeBehind="Default.aspx.cs" Inherits="MultiAuthLoginPage._Default,MultiAuthLoginPage, Version=1.0.0.0, Culture=neutral, PublicKeyToken=907bf41ebba93579" MasterPageFile="~/_layouts/simple.master" %> 
    <%@ Assembly Name="Microsoft.SharePoint.IdentityModel, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
    <%@ Register Tagprefix="SharepointIdentity" Namespace="Microsoft.SharePoint.IdentityModel" Assembly="Microsoft.SharePoint.IdentityModel, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
    <%@ Assembly Name="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"%> 
    <%@ Import Namespace="Microsoft.SharePoint.WebControls" %> 
    <%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> 
    <%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> 
    <%@ Import Namespace="Microsoft.SharePoint" %> 
    <%@ Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
    <asp:Content ID="Content1" ContentPlaceHolderId="PlaceHolderPageTitle" runat="server">
        <SharePoint:EncodedLiteral runat="server"  EncodeMethod="HtmlEncode" Id="ClaimsLogonPageTitle" />
    </asp:Content>
    <asp:Content ID="Content2" ContentPlaceHolderId="PlaceHolderPageTitleInTitleArea" runat="server">
        <SharePoint:EncodedLiteral runat="server"  EncodeMethod="HtmlEncode" Id="ClaimsLogonPageTitleInTitleArea" />
    </asp:Content>
    <asp:Content ID="Content3" ContentPlaceHolderId="PlaceHolderSiteName" runat="server"/>
    <asp:Content ID="Content4" ContentPlaceHolderId="PlaceHolderMain" runat="server">
    <SharePoint:EncodedLiteral runat="server"  EncodeMethod="HtmlEncode" Id="ClaimsLogonPageMessage" />
    <br />
    <br />
    <SharepointIdentity:LogonSelector ID="ClaimsLogonSelector" runat="server" />
    </asp:Content>
    
  11. Register your assembly in the global assembly cache.

  12. Copy your new custom default.aspx page into the C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\IDENTITYMODEL\LOGIN folder.

    Note

    Again, make a backup copy of the original default.aspx file before you do this.

  13. Repeat steps 1, 11, and 12 on every front-end web server in your farm.

That is all there is to it. I tested this with a standard user log in, and I tested opening documents directly from the Microsoft Office 2010 clients. One other thing worth noting here: These changes affect the behavior for all web applications in your farm. Again, that is why it is a simple example. However, you could easily look at the host name of the request (which maps to your web application) and make different authentication decisions based on which web application is being accessed or which site collection is being accessed. You can obviously also make other decisions based on information that you have about the current user. The HttpRequest.Context.Current class, the Page.Request class, and the Page.Response class can provide you with a lot of information to help make these kinds of decisions.

Conclusion

This article describes how to hide the default authentication provider and bypass the multi-authentication provider selection page in SharePoint 2010.

Additional Resources

For more information, see the following resources: