Remote Authentication in SharePoint Online Using Claims-Based Authentication
Summary: Learn how to authenticate against Microsoft SharePoint Online in client applications using the SharePoint client-side object models.
Applies to: Business Connectivity Services | Open XML | SharePoint Designer 2010 | SharePoint Foundation 2010 | SharePoint Online | SharePoint Server 2010 | Visual Studio
Provided by: Robert Bogue, Thor Projects, LLC (Microsoft SharePoint MVP)
Contents
Introduction to Remote Authentication in SharePoint Online Using Claims-Based Authentication
Brief Overview of SharePoint Authentication
Evolution of Claims-Based Authentication
SharePoint Claims Authentication Sequence
Using the Client Object Models for Remote Authentication in SharePoint Online
Reviewing the SharePoint Online Remote Authentication Sample Code Project
Conclusion
Additional Resources
About the Author
Download the code: Remote Authentication in SharePoint Online Using the Client Object Model
Introduction to Remote Authentication in SharePoint Online Using Claims-Based Authentication
The decision to rely on cloud-based services, such as Microsoft SharePoint Online, is not made lightly and is often hampered by the concern about access to the organization's data for internal needs. In this article, I will address this key concern by providing a framework and sample code for building client applications that can remotely authenticate users against SharePoint Online by using the SharePoint 2010 client-side object model.
Note
Although this article focuses on SharePoint Online, the techniques discussed can be applied to any environment where the remote SharePoint 2010 server uses claims-based authentication.
I will review the SharePoint 2010 authentication methods, provide details for some of the operation of SharePoint 2010 with claims-mode authentication, and describe an approach for developing a set of tools to enable remote authentication to the server for use with the client-side object model.
Brief 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.
Creating accounts with the same user name and password is a manageable problem. However, as the concern for security grew, the requirement for users to periodically change their passwords created an unmanageable situation, where the users would find it difficult to keep their passwords synchronized between different applications. Shared authentication mechanisms were developed to solve this problem. Once again, an application could rely upon a third party for authentication of the user.
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.
Today, some of the users of your application are using identities that you do not control. Consider an organization that provides payroll or retirement plan services for other companies. These organizations may need to accept users who belong to many other companies, and have no requirement to authenticate them individually. They have to know only that the organization that they have a contract with can identify the user. In these cases, the centralized server for authentication does not exist; there is no centralized entity that can validate every user.
Similarly, 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.
The ability for a claim to convey more than just simple identity necessitates the requirement to enforce rules about what types of claims an application will accept from a third party. The WS-Trust standard supports the idea that one party may rely on another party, as described previously. In addition, it also allows for a chain of trust, where the application, such as SharePoint 2010, trusts an internal provider such as Active Directory Federation Services (AD FS) 2.0, which in turn trusts another party or even multiple other parties. AD FS 2.0 creates its own claims token for SharePoint, based on the information that it received from the issuing party that it trusts. This is particularly useful because AD FS 2.0 is a claims transformation engine. That is, it can change one claim, such as a property, into another claim, such as role membership. AD FS 2.0 can also filter the claims made by a third party, so that the third party cannot pass a claim to the application that a user is an administrator for.
SharePoint Claims Authentication Sequence
Now that you have learned about the advantages of claims-based authentication, we can examine what actually happens when you work with claims-based security in SharePoint. When using classic authentication, you expect that SharePoint will issue an HTTP status code of 401 at the client, indicating the types of HTTP authentication the server supports. However, in claims mode a more complex interaction occurs. The following is a detailed account of the sequence that SharePoint performs when it is configured for both Windows authentication and Windows Live ID through claims.
The user selects a link on the secured site, and the client transmits the request.
The server responds with an HTTP status code of 302, indicating a temporary redirect. The target page is /_layouts/authenticate.aspx, with a query string parameter of Source that contains the server relative source URL that the user initially requested.
The client requests /_layouts/authenticate.aspx.
The server responds with a 302 temporary redirect to /_login/default.aspx with a query string parameter of ReturnUrl that includes the authentication page and its query string.
The client requests the /_login/default.aspx page.
The server responds with a page that prompts the user to select the authentication method. This happens because the server is configured to accept claims from multiple security token services (STSs), including the built-in SharePoint STS and the Windows Live ID STS.
The user selects the appropriate login provider from the drop-down list, and the client posts the response on /_login/default.aspx.
The server responds with a 302 temporary redirect to /_trust/default.aspx with a query string parameter of trust with the trust provider that the user selected, a ReturnUrl parameter that includes the authenticate.aspx page, and an additional query string parameter with the source again. Source is still a part of the ReturnUrl parameter.
The client follows the redirect and gets /_trust/default.aspx.
The server responds with a 302 temporary redirect to the URL of the identity provider. In the case of Windows Live ID, the URL is https://login.live.com/login.srf with a series of parameters that identify the site to Windows Live ID and a wctx parameter that matches the ReturnUrl query string provided previously.
The client and server iterate an exchange of information, based on the operation of Windows Live ID and then the user, eventually ending in a post to /_trust/default.aspx, which was configured in Windows Live ID. This post includes a Security Assertion Markup Language (SAML) token that includes the user's identity and Windows Live ID signature that specifies that the ID is correct.
The server responds with a redirect to /_layouts/authenticate.aspx, as was provided initially as the redirect URL in the ReturnUrl query string parameter. This value comes back from the claims provider as wctx in the form of a form post variable. During the redirect, the /_trust/default.aspx page writes two or more encrypted and encoded authentication cookies that are retransmitted on every request to the website. These cookies consist of one or more FedAuth cookies, and an rtFA cookie. The FedAuth cookies enable federated authorization, and the rtFA cookie enables signing out the user from all SharePoint sites, even if the sign-out process starts from a non-SharePoint site.
The client requests /_layouts/authenticate.aspx with a query string parameter of the source URL.
The server responds with a 302 temporary redirect to the source URL.
Note
If there is only one authentication mechanism for the zone on which the user is accessing the web application, the user is not prompted for which authentication to use (see step 6). Instead, /_login/default.aspx immediately redirects the user to the appropriate authentication provider—in this case, Windows Live ID.
SharePoint Online Authentication Cookies
An important aspect of this process, and the one that makes it difficult but not impossible to use remote authentication for SharePoint Online in client-side applications, is that the FedAuth cookies are written with an HTTPOnly flag. This flag is designed to prevent cross-site scripting (XSS) attacks. In a cross-site scripting attack, a malicious user injects script onto a page that transmits or uses cookies that are available on the current page for some nefarious purpose. The HTTPOnly flag on the cookie prevents Internet Explorer from allowing access to the cookie from client-side script. The Microsoft .NET Framework observes the HTTPOnly flag also, making it impossible to directly retrieve the cookie from the .NET Framework object model.
Note
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.
Using the Client Object Models for Remote Authentication in SharePoint Online
The starting point for using the SharePoint client-side object model for remote authentication is getting a ClientContext object. It is this client context object that ties the other operations in the object model to the server and specified site. 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.
For more information about PInvoke, see Calling Native Functions from Managed Code.
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.
Reviewing the SharePoint Online Remote Authentication Sample Code Project
The code sample that accompanies this article demonstrates this technique of adding the SharePoint authentication cookies to the ClientContext object. It provides a set of classes that you can use to perform federated user authentication. You can start with the sample program to see what changes you must make when using this code compared to using an HTTP authenticated web server.
The Sp_Ctx SharePoint Authentication Sample Client Application
The Sp_Ctx project is a command-line program that uses a SharePoint ClientContext object to retrieve information about the web that the context is pointed to.
Note
When using the Sp_Ctx sample, you must specify the web URL as an https request. Specifying the web URL as an http request will result in an exception.
The project refers to the ClaimsAuth library but is otherwise the same. In fact, the main code looks almost identical to the code that you would find in a standard client application.
01: static void Main(string[] args)
02: {
03: if (args.Length < 1) { Console.WriteLine("SP_Ctx <url>"); return; }
04: string targetSite = args[0];
05: using (ClientContext ctx = ClaimClientContext.GetAuthenticatedContext(targetSite))
06: {
07: if (ctx != null)
08: {
09: ctx.Load(ctx.Web); // Query for Web
10: ctx.ExecuteQuery(); // Execute
11: Console.WriteLine(ctx.Web.Title);
12: }
13: }
14: Console.ReadLine();
15: }
In this code, the only difference from code you would find in a standard client application is in line 05. Instead of creating a new ClientContext, we call ClaimClientContext.GetAuthenticatedContext. The big difference is that calling ClaimClientContext.GetAuthenticatedContext displays a form to enable the user to supply his or her credentials to the remote system, captures the authentication cookies needed to authenticate requests, and adds that header to the client context.
ClaimClientContext in the SharePoint Online Authentication Sample
Examining the next layer of the code, notice the ClaimClientContext object that was being called. It exposes two methods, the one used in the sample, GetAuthenticatedContext and GetAuthenticatedCookie. GetAuthenticatedCookie is called by GetAuthenticatedContext. In fact, GetAuthenticatedContext calls GetAuthenticatedCookie to get the cookies and wraps those in a context.
GetAuthenticatedCookie opens the dialog box that displays the website, and watches for the authentication request to complete so that the authentication cookies can be retrieved.
ClaimsWebAuth in the SharePoint Online Authentication Sample
The ClaimsWebAuth class gets the authentication cookies. It encapsulates a form and a WebBrowser object. The first step, which is performed during object construction, is to gather the login and end navigation pages. This is done through the GetClaimParams method, which makes a web request with an HTTP OPTIONS method.
When the Show method is called, the WebBrowser object is created, and an event handler is added for the Navigated event. This event is called every time the WebBrowser object is finished navigating. The event handler detects when the web browser has reached the navigation end URL. The event receiver makes the call to CookieReader, which in turn reads from WinINET to get the HTTPOnly FedAuth cookie.
With the event receiver in place, the WebBrowser is navigated to the login URL and the authentication process occurs. When it is finished, the authentication cookies are returned to the caller.
CookieReader in the SharePoint Online Authentication Sample
The final piece of the sample code is the CookieReader class, which contains the call to WinINET.dll and a helper function to get the cookie. The helper function, named GetFedAuthCookie, returns a string that represents the cookie in the form of "Name=Value." GetFedAuthCookie calls the WinINET.dll method InternetGetCookieEx to fetch the cookie.
InternetGetCookieEx returns false if the size of the string buffer that is passed in is not large enough. It also sets the size parameter to the size of buffer it needs. As a result, GetFedAuthCookie may have to call InternetGetCookieEx twice to get the value of the cookie, if the initial buffer is too small.
Conclusion
This article describes how to perform claims-based authentication for Microsoft SharePoint Online in client applications by using the SharePoint 2010 client-side object models. SharePoint Online provides a compelling and flexible option for companies that want the powerful collaborative platform of SharePoint, without the operational costs that are associated with hosting software on-premises. And, with the techniques discussed in this article, developers can use the SharePoint client-side object models to create client applications that are capable of remotely authenticating against SharePoint Online.
About the Author
Robert Bogue has been a part of the Microsoft MVP program for 8 years. Robert’s latest book is The SharePoint Shepherd’s Guide for End Users. You can find out more about the book at http://www.SharePointShepherd.com. Robert blogs at http://www.thorprojects.com/blog. You can reach Robert at Rob.Bogue@thorprojects.com.
Additional Resources
For more information about remote authentication in SharePoint Online using claims-based authentication, see the following resources: