Overview of SharePoint Authentication
In Office SharePoint Server 2007, there were two authentication types: Windows authentication, which relied upon authentication information being transmitted via HTTP headers, and forms-based authentication. Forms-based authentication used the Microsoft ASP.NET membership and roles engines for managing users and roles (or groups). This was a great improvement in authentication over the 2003 version of the SharePoint technologies, which relied exclusively on Windows authentication. However, it still made it difficult to accomplish many scenarios, such as federated sign-on and single sign-on.
To demonstrate the shortcomings of relying solely on Windows authentication, consider an environment that uses only Windows authentication. In this environment, users whose computers are not joined to the domain, or whose configurations are not set to automatically transmit credentials, are prompted for credentials for each web application they access, and in each program they access it from. So, for example, if there is a SharePoint-based intranet on
intranet.contoso.com, and My Sites are located on
my.contoso.com, users are prompted twice for credentials. If they open a Microsoft Word document from each site, they are prompted two more times, and two more times for Microsoft Excel. Obviously, this is not the best user experience.
However, if the same network uses forms-based authentication, after users log in to SharePoint, they are not prompted for authentication in other applications such as Word and Excel. But they are prompted for authentication on each of the two web applications.
Federated login systems, such as Windows Live ID, existed, but integrating them into Office SharePoint Server 2007 was difficult. Fundamentally, the forms-based mechanism was designed to authenticate against local users, that is, it was not designed to authenticate identity based on a federated system. SharePoint 2010 addressed this by adding direct support for claims-based authentication. This enables SharePoint 2010 to rely on a third party to authenticate the user, and to provide information about the roles that the user has.
Evolution of Claims-Based Authentication
Because computers are designed to accommodate multiple users, authorization has always been a challenge. At first, the operating system validated the user. Then, the operating system told the application who the user was. This was the very first claim, made by the operating system to the application. The essence of this claim was the identity of the user. The operating system had determined who the user was, probably through a password that the user provided. The application did not have to ascertain who the user was; it simply trusted the operating system.
This authentication process worked well until it became necessary for a user to use applications on systems that they were not logged in to. At this point, the application had to perform its own authentication. Applications started with the same approach that operating systems had used—requiring the user’s name and password. Authentication works well this way, but it requires that every application validate the user name and password. Maintaining multiple separate authentication databases became problematic, because users would want to use their same user names and passwords across applications.
The most popular approach for a shared authentication database is one that uses the Kerberos protocol. The Kerberos protocol provides mechanisms that enable a user to authenticate against a centralized server and then convey his or her identity through a ticket signed by that server. The advantage of this approach is that the centralized server is the only one that must know the user’s password or other identifying information. This works well for providing authentication information, but it relies on a single store for user identities.
If you have an extranet website that is designed to work with multiple partners, you may not want to manage user accounts for all of your partners’ employees, or even let the partners manage them. Instead, you just want to take the remote server’s claim of the user’s identity.
This is one of the great features of a claims-based login. Another system, which your system trusts, provides a claim of the user’s identity.
There are many standards, such as WS-Federation, WS-Security, and WS-Trust that define how this sort of arrangement should work. WS-Federation is the most relevant because it describes a specific approach for the exchange of federated authentication. SharePoint 2010 implements the WS-Federation standard, as do many other Microsoft and non-Microsoft products. This means that the SharePoint claims implementation can talk to many other systems.
In addition to the authentication information described previously, there is the capability for the infrastructure to make other claims about the user, including profile properties such as name and email address. The claim can also contain the roles, or groups, that a user belongs to. This opens the door for applications, including SharePoint 2010, to use what the claims provider (known as an issuing party) trusts about the user. Then, applications can set authorization to do something to the roles that are conveyed in the claims token.
SharePoint Online Authentication Cookies
For SharePoint Online, the FedAuth cookies are written with an HTTPOnly flag. However, for on-premises SharePoint 2010 installations, an administrator could modify the web.config file to render normal cookies without this flag. The HTTPOnly flag on the cookie prevents Internet Explorer from allowing access to the cookie from client-side script.
Using the Client Object Models for Remote Authentication in SharePoint Online
In a Windows-based HTTP authentication scenario, the client context behaves as Internet Explorer behaves; it automatically transmits credentials to the server if the server is in the Intranet zone. In most cases, this works just fine. The server processes the credentials and automatically authenticates the user.
In a forms-based authentication environment, it is also possible to use the FormsAuthenticationLoginInfo object to provide forms-based authentication to the server. However, this works only for forms-based authentication. It does not work for federated-based claims scenarios because SharePoint does not own the actual authentication process.
Creating an authenticated ClientContext object is a multistep process. First, the user must be able to sign into the remote system interactively. First, the user signs into SharePoint through the federated authentication provider, and SharePoint must issue its authentication cookies. Second, the code must retrieve the authentication cookies. Third, those cookies must be added to the ClientContext object.
Enabling User Login for Remote Authentication
The .NET Framework includes a System.Windows.Forms.WebBrowser object that is designed to enable the use of a web browser inside of an application. To enable the user to log in to the federated authentication provider, this object must be created and displayed. The goal, however, is to retrieve the authentication cookies issued by SharePoint Online. To determine when the login process is completed, you must register a handler on the Navigated event. This event fires after the browser has completed navigation. This event handler watches for the user to be returned to the URL that they started navigating from. When this occurs, the code knows that the user has completed the login sequence.
Fetching the SharePoint Authentication Cookies
Because the FedAuth cookies are written with an HTTPOnly flag, they cannot be accessed from the .NET Framework. To retrieve the cookies, a call must be made to the WININET.dll. The .NET Framework can call COM-based DLL methods through PInvoke (platform invoke). In this case, the method to be called is InternetGetCookieEx. This can return regular cookies and those with the HTTPOnly flag. However, this method works only by starting with Internet Explorer 8. After the cookie is retrieved, it must be added to the client context.
Adding the SharePoint Authentication Cookies to the ClientContext object
The final step is to retrieve the authentication cookies from the user’s login and to attach them to the client context. Unfortunately, there is no direct way to add the cookies to the request. However, there is an event, ExecutingWebRequest, which is called before the ClientContext object makes a request to the server. By adding an event handler to this event, you can add a new request header with the authentication cookies. After this is complete, the ClientContext object can be used normally, and the rest of the code is completely unaware that the authentication is based on a federated authentication.