Friday, February 15, 2013

How to Change Accounts once you are Logged In to a Site (using SharePoint SDK for Windows Phone)

We need a set up for today's post:
  • You created a Windows Phone using the SharePoint SDK for Windows Phone. 
  • A user logs in to Site A using his Microsoft Account*.
  • He checks the box Keep me signed in
  • Later he wants to log in to Site B using different credentials than the previous one.
He will get an error:
Error: Access Denied,  "You are not a member of this site."

The problem: Site A credentials will be used for accessing Site B. The user is offered no way to enter new credentials for Site B.

Sticky Credentials

When using MicrosoftOnline as authentication method with the SharePoint SDK the user is presented with a web-based login dialog the first time he accesses the site. The user enters his credentials and can choose to stay signed in by checking Keep me signed in.

If he chooses to be kept signed in the login dialog will not be presented again.

"Keep me signed in" (the German version)

And this can be a problem. These credentials are the definition of "sticky" as it seems to be impossible to get rid of them via code.

You might ask: Why do we want to get rid of them in the first place?

Here's why: If the user tries to access another site (Site B) which requires different credentials than Site A his Site A credentials will still be used. This of course doesn't work and he will be presented with the nice "Access denied" message above.

Discarding the Credentials: #fail

I tried quite some time to delete the sticky credentials via code.

How are credentials stored? They might be cached AES-encrypted to the local store along with cookies from the browser. These cookies will be obtained from the web browser component used for logging the user in (the browser being part of the embedded XAML-based login dialog).

But this caching of cookies needs to be enabled explicitly by setting CookieCachingEnabled to true. It's disabled by default. In my attempt to dispose the sticky login I was lead astray by these methods related to caching:
  • Authenticator.ClearAllApplicationSettings
  • Authenticator.ClearAllCookies
  • Authenticator.ClearAllCredentials
While these might clear the internal cache, they didn't solve my problem. The user was still logged in with his Site A credentials.

I then started to believe (and still do) that the login information is simply stored as "normal" cookies somewhere. I verified that there are lots of cookies related to my SharePoint activities. I used the GetCookies extension method for WebBrowser to get a list of cookies which revealed 14 cookies for the domain login.microsoft.com: WLOpt, PPAuth, MSPPre, MSPCID, RPSTAuthTime, MSPVis, MSPSoftVis, MSPRequ, MSPBack, PPLState, RPSTAuth, MSPAuth, MSPProf, MH.

Unfortunately this cookie collection is read-only, so no chance of modifying (or clearing) it. And I still don't know how to manipulate these cookies. If you do then help me out on StackOverflow!

Offering the User to Log In with Different Credentials

In the end I chose a workaround which is rather simple. I navigated to login.microsoftonline.com in the desktop browser and used Fiddler to look at the requests that were being made when I logged out by actively clicking on Sign Out.

It navigates to https://login.microsoftonline.com/logout.srf. And that's all it takes.

In code, navigate to the above URL and the next time the user accesses any site he will see this:

The highlighted link says: "Sign in with another User ID"

(Usability note: On the right site the dialog is cut off because it is too wide for the phone screen. It's not the screenshot being cropped. Ugly.)

But finally the user can click the highlighted link to sign in with another ID.



* Forgive me if I sometimes refer to the credentials being entered by the wrong name. There are just so many terms to choose from (some old, some new).
  • Microsoft Online Services ID
  • Microsoft Account
  • User ID
  • MicrosoftOnline (= name of authentication method in code)