Question

I am working on a REST-based app that connects to Office365. The app will be available on multiple platforms, so I have created a portable class library to handle all the logic, including authentication. The PCL targets Windows Phone 7.1 and onwards, and includes the Microsoft HTTP Client Libraries (NuGet), which is required for Windows Phone 7.1 apps.

The last step of the authentication for Office365 is to get a FedAuth cookie from the site, and that is where I am having a problem.

The code I use to get the cookie is:

var handler = new HttpClientHandler();
handler.AllowAutoRedirect = false;
var newClient = new HttpClient(handler);
var newResponse = await newClient.PostAsync(host + "/_forms/default.aspx?wa=wsignin1.0", new StringContent(binarySecurityToken));

The 'host' variable is just the URL of the Office365 site, and the binarySecurityToken I got from previous requests. These things work equally well in all the apps: Whether I run the PCL code from the context of a Windows Phone 7.1 app, Windows Phone 8 app, Windows 8 app, or even a Console application, I am getting exactly the same response (see below), which contains the FedAuth cookie. This I have verified using Fiddler.

Then I try to get the cookie to reuse it on subsequent requests.

var cookieCollection = handler.CookieContainer.GetCookies(new Uri(host));
foreach (var cookie in cookieCollection)
{
    if (cookie.Name.StartsWith("FedAuth"))
    {
        //TODO: Store the cookie.
        return true;
    }
}

This leads to the following result: On Windows Phone 7.1 the 'cookieCollection' variable only contains the cookie rtFa'. On the other platforms it contains all three cookies 'RpsContextCookie', 'rtFa', 'FedAuth'.

Windows Phone 7.1 differs from the other apps in that this is the only platform that actually uses the HttpClient from the NuGet package. The other platforms have a native HttpClient that is swapped in by the magic of PCL.

It seems likely that the problem is caused by the FedAuth cookie not having a domain. I have tried using .GetCookies(null), and different variations of .GetCookies(new Uri("something", UriKind.Relative)), which all result in an exception. I have also tried changing most of the properties of the HttpClientHandler without luck.

Has anyone encountered this problem, and perhaps solved it? Or just a suggestion on what I could try?

The response I get on the .PostAsync above is the same on all platforms, and according to Fiddler the raw response is:

HTTP/1.1 302 Found
Cache-Control: no-cache, no-store
Pragma: no-cache
Content-Type: text/html; charset=utf-8
Expires: -1
Location: /
Server: Microsoft-IIS/7.5
X-SharePointHealthScore: 0
X-AspNet-Version: 4.0.30319
Set-Cookie: RpsContextCookie=; path=/
Set-Cookie: rtFa=+13jGMMp0A0V+driESaO30ixYclFCRjEvS2jMSwXPfQcrefiJvLEExxYu7V+1JZHM6X5JWeuL70jb3/N/Q/hUTwoAiC/XLJZ1QfERi4aUt8AAVF4ekcNyMdWnj65foDwPkhaV5z8whNSZQigBFD/2Vc1xMTH0ukHbS4cbtJO5U28/4g66vgIZg7dGpNOZg2jDt+HF3GSQ4/W+T1oS9/F5e+Pbwd0p8mqPhkGjL+M7IptmkeHoIqVcS4Ps25dM6q1AniLiv/3NujYmrQjseaEYZ2aaCfc7ZHX7LygBZm8KsoGNyTYRPmC+hZ7tsDq6wfto+xVpX1scggsU0+Qty3DPWUiwy1bBy8JR0znFG0+eDt9uBOQzqfOSjVvd8WNIKUFIAAAAA==; domain=sharepoint.com; path=/; HttpOnly
Set-Cookie: FedAuth=77u/PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48U1A+RmFsc2UsMGguZnxtZW1iZXJzaGlwfDEwMDMwMDAwODc5MTUwMGVAbGl2ZS5jb20sMCMuZnxtZW1iZXJzaGlwfHRtakB3aWxkY293Lm9ubWljcm9zb2Z0LmNvbSwxMzAzNDIwOTYxNDAxMTIxMzMsRmFsc2UsV2lSQjlUVTdOSTk0MUpKRWZ5d1JDNTFPYUphMVpWNkJqWWdaVGM3MU00U3lqL2VkTnF6dVJpbXdEMnpEWk9oR1lybkFsNnpWb3M4V0FBZDk1VVYrZkt5dlkwQ3dqRTlyaEhEc256bkZUeENoODU1Rm1JZmxoYVBkMTFQS2VjWnFJN0N4OUxUOHk4enZDaVNUTGNQMzR2K3NOeHk1YXBMZ2NIWDNHR3JMcG1Ic24rQzAzUkUzakNDQWhma2F3RVRQbk03R3JycVk5amJseHJmNVNhNHZxMk91NlN1cGszZnpQMUZQTzJBc1UrRXZvSDgvWTllR2Y3c2x2dStvMnVlN3hZLy9VQ1lYU1U4b3AzckZ6c2laK0wwN1NrUnZYMTZjVklUVVZJZ0x6TGIxaTJLd2lwNGp6RHgwRFdmVWF0Rk42UVFaNWhHRzMyOHRJZjI2RXo4YldnPT0saHR0cHM6Ly93aWxkY293LnNoYXJlcG9pbnQuY29tLzwvU1A+; path=/; secure; HttpOnly
SPRequestGuid: 5bb2689c-d7c5-c07c-4890-ee32437f15f5
request-id: 5bb2689c-d7c5-c07c-4890-ee32437f15f5
SPRequestDuration: 125
SPIisLatency: 2
X-Powered-By: ASP.NET
MicrosoftSharePointTeamServices: 16.0.0.2308
X-Content-Type-Options: nosniff
X-MS-InvokeApp: 1; RequireReadOnly
P3P: CP="ALL IND DSP COR ADM CONo CUR CUSo IVAo IVDo PSA PSD TAI TELo OUR SAMo CNT COM INT NAV ONL PHY PRE PUR UNI"
Date: Thu, 09 Jan 2014 21:46:53 GMT
Content-Length: 118

<html><head><title>Object moved</title></head><body>
<h2>Object moved to <a href="/">here</a>.</h2>
</body></html>
Was it helpful?

Solution

I found an answer of kind here: Accessing HTTPOnly cookies from Windows Phone 8/PCL.

Reading the post I realized that I made an error above: I was not getting the 'rtFa' cookie in the Windows Phone 7.1 app, but the 'RpsContextCookie'. The cookies I couldn't access were both marked with HttpOnly.

I also realized that I don't need to access the cookies directly. Instead, I could just reuse the handler.CookieContainer. So my code now looks like this:

var handler = new HttpClientHandler();
handler.AllowAutoRedirect = false;
var newClient = new HttpClient(handler);
var newResponse = await newClient.PostAsync(host + "/_forms/default.aspx?wa=wsignin1.0", new StringContent(binarySecurityToken));
this._cookieContainer = handler.CookieContainer;
return true;

this._cookieContainer is just a class-scoped field for storage of the cookie container. Then, once I am authenticated and I do the requests that are the actual purpose of the app, I do the following:

var handler = new HttpClientHandler(){ CookieContainer = this._cookieContainer };
var client = new HttpClient(handler);
var response = await client.GetAsync(host + "something");

So the bottom line is: I can't access the HttpOnly cookies - but I don't need to. I just reuse the cookie container, and the cookies are automatically included in the next request.

This works both in Windows Phone 7.1 apps, Windows Phone 8 apps, Console applications etc.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top