SharePoint 2010: transparent login with mixed authentication 

Tags: SharePoint 2010, SharePoint

Authentication in SharePoint 2007

In SharePoint 2007 it was possible to enable forms based authentication next to windows authentication only by extending a web application and basically running two separate applications on the same content database.

side from the problems with forms based authentication in SharePoint 2007, there were also some usability issues.

  • The two sites are accessed by a different url. For internal users the url could be https://intranet, for external users https://intranet.company.com.
    This is especially a problem when sending links to document or pages. The links point to a different site depending on if an internal or external user copied the link. This lead to a lot of confusion and unexpected errors
  • Email alerts sent by SharePoint itself can contain the wrong urls
  • Smartparts and some other customisations need to be deployed twice
  • Changes to the web.config need to be duplicated

Authentication in SharePoint 2010

SharePoint 2010 comes with a nice new feature that aims to solve this problem: Mixed Authentication. It allows for the configuration of multiple authentication providers (Windows authentication, forms authentication, trusted Identity providers) together using the same url, without having to extend the web application. Both external and internal users would access the web site on https://intranet.company.com for example.

By default the user has to choose the authentication method when upon logging in.

image

While this is very nice, and a great improvement over the previous version, the downside is that there is no more transparent authentication in an intranet environment.

With the correct browser settings is it possible to log on automatically when using windows authentication.

In Internet Explorer it can be configured in the security settings of the Local Intranet zone. These settings can also be pushed through group policies.

image

image

If the intranet is configured correctly, or “detected automatically”, all login attempts will transparently use the windows identity.

Each time a user tries to access the intranet, he is greeted by the “user friendly” choice above. Each time he tries to open a document stored on the intranet, he gets the same login popup.

In an intranet environment, this is simply unacceptable.

The solution for SharePoint 2010

Looking to improve on this situation we found a great blog post by Bryan Porter. By using a custom login page and custom PowerShell snap-in he was able to automatically choose the authentication provider based on the IP address of the user logging in.

The solution consists of two parts

  • A custom PowerShell snap-in that is used to manage the mappings between IP addresses and authentication providers. The mapping is stored in the Hierarchical Object Store, on the level of the Web Application.
  • A custom sign-in page. When the custom sign-in page is loaded it will first check the IP address of the user. Then it will check if the address is mapped to an authentication provider. If it is mapped, the user will be redirected to the sign-in page of that provider. In other words, if the mapping is found the “Select the credentials you want to use to logon to the SharePoint site” step of the sign in process is automated.

In order to use Bryan’s solution we added some features:

  • Wild card mapping. Authentication providers can now be mapped to wildcard IP range, for example 192.168.0.*
  • IPv6 support.
  • Fix the redirection to make “Sign in as a different user” work correctly

After installing the web application can be configured to automatically use Windows Authentication for a certain range of IP’s, and forms authentication for the others.

Update: The project is now available on codeplex: http://spautomaticsignin.codeplex.com/

We are currently using this solution for several customers.

 

Deployment

All commands are executed in the SharePoint 2010 Management Shell

The custom login page is deployed to the SharePoint Root: “C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\IDENTITYMODEL\LOGIN”

The assembly containing the code-behind of the login page and the powershell cmdlet code are deployed to the GAC

  1. Add the solution to the solution store

    stsadm -o addsolution -filename OrbitOne.SharePoint.Claims.SignIn.wsp

  2. Deploy the solution to all web applications

    stsadm -o deploysolution -name OrbitOne.SharePoint.Claims.SignIn.wsp -immediate -allowgacdeployment

    stsadm -o execadmsvcjobs

  3. Register the assembly

    C:\WINDOWS\Microsoft.NET\Framework64\v2.0.50727\installutil /assemblyname "OrbitOne.SharePoint.Claims.SignIn, Culture=neutral, Version=1.0.0.0, PublicKeyToken=3c7a593397c60142"

Deployment of an updated version

  1. Retract and delete the existing solution

    stsadm -o retractsolution -name OrbitOne.SharePoint.Claims.SignIn.wsp -immediate

    stsadm -o execadmsvcjobs

    stsadm -o deletesolution -name OrbitOne.SharePoint.Claims.SignIn.wsp

  2. Deploy the new solution

    stsadm -o addsolution -filename OrbitOne.SharePoint.Claims.SignIn.wsp

    stsadm -o deploysolution -name OrbitOne.SharePoint.Claims.SignIn.wsp -immediate -allowgacdeployment

    stsadm -o execadmsvcjobs

  3.  

Configuration

In the SharePoint 2010 Management Console:

load the snap-in

Add-PSSnapin ClaimsSignInAdmin

Create a configuration object. Note: the url is the url of your web application

$config = Get-SPSignInConfiguration –webapplication “http://www.website.com”

Mappings can be managed with the following commands

  • View all configured mappings

    $config.ProviderMappings

  • Add a mapping

    $config.ProviderMappings.Add("192.168.20.*","Windows Authentication")

    $config.Update()

  • Remove a mapping

    $config.ProviderMappings.Remove("192.168.20.*")

    $config.Update()

  • Clear all mappings

    $config.ProviderMappings.Clear()

    $config.Update()

 

Configure the custom sign-in page

Configuration of a custom sign-in page is now a fully supported feature. In SharePoint 2007 it was possible to do this in the web.config, in Sharepoint 2010 it is a settings in the Central Administration.

Application Management -> Manage Web Applications

Select one - > Authentication providers –> select the Zone (usually Default)

image

Is there a way to do this from Powershell? It would make the deployment a lot faster.

Code

The IP address to Authentication provider mappings are stored in the Hierarchal Object Store associated with a web application. To create a custom Persisted Object for SharePoint all that is needed is to inherit from SPPersistedObject and mark the fields to persist with the “Persisted” attribute.

public class SignInConfiguration : SPPersistedObject
{
    [Persisted()]
    private Dictionary<string, string> m_providerMappings = new Dictionary<string, string>();
    
    public SignInConfiguration(): base()
    { }

    public SignInConfiguration(string name, SPPersistedObject parent): base(name, parent)
    { }

    public SignInConfiguration(string name, SPPersistedObject parent, Guid id): base(name, parent, id)
    { }
    
    public Dictionary<string, string> ProviderMappings
    {
        get { return m_providerMappings; }
    }
}

To add this object to a web application or to get an existing one from a web application a custom PowerShell cmdlet is used

[Cmdlet("Get", "SPSignInConfiguration", DefaultParameterSetName = "DefaultSet")]
public class SPCmdletGetSignInConfigObject : SPCmdlet
{
   private SPWebApplicationPipeBind m_webAppPipeBind;

   protected override void InternalProcessRecord()
   {
       SPWebApplication webApp = m_webAppPipeBind.Read();
       SignInConfiguration sc = webApp.GetChild<SignInConfiguration>("SignInConfig");
        
       if (sc == null)
       {
           sc = new SignInConfiguration("SignInConfig", webApp);
       }

       sc.Update();
       base.WriteObject(sc);
   }

   [ValidateNotNull]
   [Parameter(Mandatory=true, ValueFromPipeline=true, Position=0)]
   [Alias(new string[] { "WebApplication", "WebApp"})]
   public SPWebApplicationPipeBind Identity
   {
       get { return m_webAppPipeBind; }
       set { m_webAppPipeBind = value; }
   }
}

A SignInConfiguration object is returned for the specified web application. If the configuration does not exist yet a new one will be created. This gives us a reference to the SingInConfig object in the Powershell environment. Any changes are persisted after calling the Update() method on the object.

Finally, in the code behind of the login page the mappings are retrieved, the IP address of the request is checked against the mappings, and if an authentication provider is found the user is redirected to the provider’s sign-in page.

protected override void OnLoad(EventArgs e)
{
  if (SPContext.Current == null) return;
  if (SPContext.Current.Site == null) return;
  if (SPContext.Current.Site.WebApplication == null) return;

  SPWebApplication app = SPContext.Current.Site.WebApplication;
  SignInConfiguration config = app.GetChild<SignInConfiguration>("SignInConfig");

  SPAlternateUrl u = app.AlternateUrls[Request.Url];
  SPUrlZone zone = u.UrlZone;

  string components = Request.Url.GetComponents(UriComponents.Query, UriFormat.SafeUnescaped);
  SPIisSettings settings = app.IisSettings[zone];

  string ip = IpNetworking.GetIP4Address();
  ip = Regex.Replace(ip, @"^(?<Prefix>(\d{1,3}\.){3})\d{1,3}$", "${Prefix}*");
  if (config != null && config.ProviderMappings.ContainsKey(ip))
  {
      string targetProvider = config.ProviderMappings[ip];
      foreach (SPAuthenticationProvider provider in settings.ClaimsAuthenticationProviders)
      {
          if (string.Compare(provider.DisplayName, targetProvider, true, System.Globalization.CultureInfo.CurrentUICulture) == 0
              || string.Compare(provider.ClaimProviderName, targetProvider, true, System.Globalization.CultureInfo.CurrentUICulture) == 0)
          {
              string url = provider.AuthenticationRedirectionUrl.ToString();
              if (provider is SPWindowsAuthenticationProvider)
              {
                  components = EnsureReturnUrl(components);
              }
              SPUtility.Redirect(url, SPRedirectFlags.Default, this.Context, components);
          }
      }
  }
  else
  {
      SPUtility.Redirect("/_forms/default.aspx", SPRedirectFlags.Default, this.Context, components);   
  }
  base.OnLoad(e);
}
 
Posted by Mel Gerats on 23-Jun-10
14 Comments  |  Trackback Url | Bookmark this post with:        
 

Comments


Ahmed Sherien commented on Monday, 28-Jun-2010
your work is just great ... but I'm a fresher when it comes to SharePoint ... so I really don't know where to put that code you mentioned ... I would ask for a little more explanation about that part of setting things up please ...


Steve commented on Wednesday, 28-Jul-2010
Thanks for the article. We have made the custom login page and it works great using HTTP://domainname however when trying to access the site ussing https, we get a resource not found error. Reverting back to the default login page HTTPS works fine. Any idea on how to deploy this for an SSL enabled site?


Shahid Mahmood commented on Monday, 13-Sep-2010
Same here Steve, the component works for an http site but doesnt work for a secured site. Any comments from the authors is appreciated.


Rowan Graham West commented on Thursday, 23-Sep-2010
Great article. Thanks for sharing this information. I have just hosted my site with http://www.asphostportal.com. Everything looks very good and their support is nice. Just info for all of you if you're looking for sharepoint 2010 hosting.


jason commented on Tuesday, 22-Feb-2011
Any advances on the https issues, or was this just a user config blooper


prvanbeek commented on Monday, 7-Mar-2011
I've implemented the solution, configured the provider mappings with a wild card, e.g., 10.*.*.*, and I am always redirected to the forms login page. Any ideas on what I may have missed?


Daniel Westerdale commented on Monday, 21-Mar-2011
Hi Firstly, I agree with your comment re using PowerShell to set the autoSignin.aspx. on the web app in question. I understand I have recreate my existing web app and set Claims based authentication and the custom login screen. You can't simply do this via Central Admin


Martin Poirier commented on Thursday, 16-Jun-2011
We require 3 authentication provides. Two different window authentication (2 Different Domain) and one FBA. Can you solution support this type of scenario?


Tim commented on Tuesday, 12-Jul-2011
Hi there, thanks for the great article. I have things successfully setup (note for those people having issues with SSL, I found that if you setup SSL on an extended web application vs. just an AAM and perform the configuration against the extended web application then it appears to work fine). Also - prvanbeek it looks like the wild card is just supported for the last IP block (have not verified but the regular expression in the redirect looks to focus on the prefix only). One question / issue I have is when you consider internal users accessing the system externally (e.g. working from home without VPN). The IP detection works fine when they are in the office and defaults to windows authentication. If a customer or similar accesses externally then they can authenticate with FBA. If an "internal" (staff with an AD account) want to login from home they can't as when they fail the IP check they will be defaulted to logging in via FBA. Are there any suggestions as to how I could have internal users auto logged in (as works at the moment) but instead of the alternative being FBA, being the original login screen where they get to select from Windows/FBA login? Hope this makes sense.


Rancy commented on Monday, 25-Jul-2011
Hi, I depoloyed the solution and when I go to the site I get error "The given key is not found" and it gives stack of errors. I have two authentication methods (Windows and ADFS) on the SSL enabled site. Does anyone have any idea why this could be happening? Thanks


Luciana Pedroso commented on Friday, 29-Jul-2011
Hi I installed the wsp, i put the ip range but when i open the site the white page opens and nothing more.whould be?


Wim De Coninck commented on Thursday, 11-Aug-2011
Hey Rancy, I just answered in the codeplex discussion of this project http://spautomaticsignin.codeplex.com/discussions


Wim De Coninck commented on Thursday, 11-Aug-2011
Luciana, Could you check the SignInPage configuration in your sharepoint site? Also there is a feature in there where you can choose different sign in pages / authentication provider. Maybe a config got in there? follow the steps in the documentation (on codeplex) on configuration to get started and doe a $config.SingInPageMappings to see them. Hope this helped. Let us know


David Godin commented on Thursday, 8-Dec-2011
From experience, AAM should never be used on their own to map/enable new zones in SharePoint (such as when you want to add an https URL or an additional URL to an existing WebApp). I know there are tons of blogs out there showing you how to do this using AAM. It seems to work fine but doing it this way will eventually get you into trouble. One of those cases is when playing with authentication providers, but there are other cases, trust me. You should always extend WebApps to add URLs. The reason is the SharePoint object model in many case, but not all cases, expects to find a WebApp objet behind a Zone, such as when assigning custom login pages (it’s assign to the WebApp, not the zone) or adding a new provider (same thing here). If you just add a new AAM URL to a zone to have an additionnal https URL it won’t create that necessary WebApp objet. I have read that Extending WebApp eats up unnecessary resources. Wrong! It’s a simple IIS binding to the same instances of the SharePoint code (same AppPool) so it’s negligible. Use AAM (Internal and/or Public) only to tweak URLs when doing URL rewrite with devices such as Load-Balancers, proxy servers and firewalls. It’s why MS invented AAMs. So if you want to use this solution and possibly prevent future issues (if you have used AAM to create new zones) extend your WebApp with the new URL so that you have a WebApp for every single one of them.

Your name  *
Email  *
Your URL 
Comment  *

Please enter the text from the image


Orbit One on LinkedIn
Contact us - Raas Van Gaverestraat 83, 9000 Gent, Belgium - Tel. +32 (9) 330.15.00 - Privacy Statement - Sitemap - Sign In Developed with Microsoft Office SharePoint Server 2007