This is a post detailing how you perform active authentication to SharePoint Online in Office 365. Active authentication is required when you need to authenticate in code to programmatically access SharePoint objects, using for instance Client Object Model, web services or WebDAV from outside of Office 365. When you are “in” SharePoint Online or using the web browser this is not needed since you are either already authenticated and the web browser handles the authentication using active authentication.
Note: The active authentication “mechanism” have unfortunately changed a few times the last month without any notice. I had a really bad timing with one of these changes just a couple of days before demoing it on TechDays here in Sweden. With that said - I cannot guarantee that this method will work in the future. But if it changes I’ll try to update the post or write a new one…
SharePoint Online active AuthN basics
Before digging into the actual code I think it is important to understand how it actually works and what the code does. This is easier done using a diagram.
What happens is that we need to request a token from the STS. In Office 365 the STS is located at https://login.microsoftonline.com/extSTS.srf. To request the token from the STS we pass the username and password using the SAML 1.1 protocol. If the authentication is successful the STS returns a security token. This security token is sent to SharePoint and if SharePoint successfully validates the token it will return two cookies (called FedAuth and rtFa). These two tokens must then be passed along with all requests to SharePoint.
There are some other interesting things happening here that you need to be aware of. For instance; you need to be aware of which Office 365 subscription you are targeting. P-subscriptions must use HTTP Url’s when communicating and E-subscriptions must use HTTPS. Using HTTPS for P-subscriptions will create redirect responses that eventually will drive you crazy when trying to code around them (I got a solution for that though - but I can’t get any worse anyways).
How to use Client Object Model with Office 365 from a remote client
To be able to remotely invoke methods on SharePoint Online using Client Object Model (CSOM), web services or WebDAV we need to authenticate first, according to above. Then we need to pass along the cookies for each request. And this is how we do it. Once you have the cookies (FedAuth and rtFA) you need to create a CookieContainer object in which you add the cookies. This CookieContainer must then be added to the request done by the Client Object Model before the request is done. The client runtime Context object has an event called ExecutingWebRequest that can be used for this. The code could look something like this:
context.ExecutingWebRequest += (s,e) => {
e.WebRequestExecutor.WebRequest.CookieContainer =
createCookieContainer();
e.WebRequestExecutor.WebRequest.UserAgent = userAgent;
};
The createCookieContainer() method is the one responsible for creating the cookie container, more on this one later. Also note here that I set the UserAgent of the request to a new value. This is important! If you do not set any user agent of this request SharePoint Online will gently throw a 403 Forbidden error if you’re on an E-subscription. It works fine without on P-subscriptions, but it doesn’t harm to add it. So just do it all the time, for the sake of it! The user agent could be any normal browser - this is what I use:
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)"
That’s basically it! Use the same procedure when you’re manually using WebRequest objects or when you’re using the SharePoint web services. Just add the cookies and user agent and you’re fine.
Show me the code to get the cookies!
Now to the core of this article. How does the code look like to get the actual cookies? As a good TV-chef I’ve prepared all the things you need to make it really easy for you. I’ve been using a number of helper classes for a couple of months now and first showed them during TechDays 2011. Chris Johnson, Microsoft, also made a version of them for his blog post on the topic. My helper class has an origin in posts from Steve “SharePoint Claims” Peschka. I’ve modified and tweaked his code samples so that they work with SharePoint Online.
What I’ve done is a helper class called MsOnlineClaimsHelper. This class contains all you need to authenticate, retrieve and cache the cookies and piggyback the cookie container on the CSOM web requests. Let’s see a very simple sample:
MsOnlineClaimsHelper claimsHelper = new MsOnlineClaimsHelper(url, username, password);
using (ClientContext context = new ClientContext(url)) {
context.ExecutingWebRequest += claimsHelper.clientContext_ExecutingWebRequest;
context.Load(context.Web);
context.ExecuteQuery();
Console.WriteLine("Name of the web is: " + context.Web.Title);
}
On the first line I create the helper object and pass in the URL, username and password. This class will once used do the active authentication for you and cache the cookies until they expire. It will handle the HTTP/HTTPS problem with the E/P-subscriptions mentioned earlier, the User Agent problem and everything else you need. Yes, you will be able to download the code later. After creating the client context I hook up a helper method of the MsOnlineClaimsHelper class called clientContext_ExecutingWebRequest. This method is the one adding the cookies and fixing the user agent. Then it’s just to use the client object model as usual. Remember that when you are using P-subscriptions the URL’s passed into the client object model must be HTTP (the helper class doesn’t really care and can handle both) and use HTTPS for E-subscriptions.
The helper class is made so that you can reuse it, so you don’t have to re-authenticate all the time, since that will really slow your application down. If you need the CookieContainer to add to your own web requests it has a property called (surpise!) CookieContainer that you can use.
To illustrate another use, that also is a very useful helper class, is a Office 365 claims aware WebClient derivative.
public class ClaimsWebClient : WebClient {
private readonly MsOnlineClaimsHelper claimsHelper;
public ClaimsWebClient(Uri host, string username, string password) {
claimsHelper = new MsOnlineClaimsHelper(host, username, password);
}
protected override WebRequest GetWebRequest(Uri address) {
WebRequest request = base.GetWebRequest(address);
if (request is HttpWebRequest) {
(request as HttpWebRequest).CookieContainer = claimsHelper.CookieContainer;
}
return request;
}
}
This is a class that can be used just as the normal WebClient class. Using this one you enable WebDAV fiddling with SharePoint Online. It’s very useful to upload and retrieve documents using PUT and GET methods.
The download
I promised you to see the code how we actually retrieves the cookies. Sorry, I won’t. I’ll leave that to you. Download the code sample, including all helper classes, by clicking this link and experiment with it as you like.
Happy coding!
Updated: Sometimes you’re tired - mixed up passive and active…