One of the projects that’s been kicking around in the back of my head is how to make Windows Phone 7 applications able to authenticate against a Windows domain. This is a must have for enterprise developers if they want to use the new platform.
There were a couple ways I could do this, but keeping with my Claims-shtick I figured I would use an STS. Given that ADFS is designed specifically for Active Directory authentication, I figured it would work nicely. It should work like this:

Nothing too spectacularly interesting about the process. In order to use ADFS though, I need the correct endpoint. In this case I’m using
https://[external.exampledomain.com]/adfs/services/Trust/13/usernamemixed
That takes care of half of the problem. Now I actually need to make my application call that web service endpoint.
This is kind of a pain because WP7/Silverlight don’t support the underlying protocol, WS-Federation.
Theoretically I could just add that endpoint as a service reference and build up all the pieces, but that is a nightmare scenario because of all the boiler-plating around security. It would be nice if there was a library that supported WS-Federation for the phone.
As it turns out Dominick Baier came across a solution. He converted the project that came from the Identity training kit initially designed for Silverlight. As he mentions there were a few gotchas, but overall it worked nicely. You can download his source code and play around.
I decided to take it a step further though. I didn’t really like the basic flow of token requests, and I didn’t like how I couldn’t work with IPrincipal/IIdentity objects.
First things first though. I wanted to start from scratch, so I opened the identity training kit and looked for the Silverlight project. You can find it here: [wherever you installed the kit]\IdentityTrainingKitVS2010\Labs\SilverlightAndIdentity\Source\Assets\SL.IdentityModel.
Initially I thought I could just add it to a phone project, but that was a bad idea; there were too many build errors. I could convert the project file to a phone library, but frankly I was lazy, so I just created a new phone library and copied the source files between projects.
There were a couple references missing, so I added System.Runtime.Serialization, System.ServiceModel, and System.Xml.Linq.
This got the project built, but will it work?
I copied Dominick’s code:
WSTrustClient _client;
private void button1_Click(object sender, RoutedEventArgs e)
{
_client = GetWSTrustClient(
https://[...]/adfs/services/Trust/13/usernamemixed,
new UsernameCredentials("username", "password"));
var rst = new RequestSecurityToken(WSTrust13Constants.KeyTypes.Bearer)
{
AppliesTo = new EndpointAddress("[…]")
};
_client.IssueCompleted += client_IssueCompleted;
_client.IssueAsync(rst);
}
void client_IssueCompleted(object sender, IssueCompletedEventArgs e)
{
_client.IssueCompleted -= client_IssueCompleted;
if (e.Error != null)
throw e.Error;
var token = e.Result;
button2.IsEnabled = true;
}
private WSTrustClient
GetWSTrustClient(string stsEndpoint, IRequestCredentials credentials)
{
var client = new WSTrustClient(new WSTrustBindingUsernameMixed(),
new EndpointAddress(stsEndpoint), credentials);
return client;
}
To my surprise it worked. Sweet.
This left me wanting more though. In order to access any of the claims within the token I had to do something with the RequestSecurityTokenResponse (RSTR) object. Also, how do I make this identity stick around within the application?
The next thing I decided to do was figure out how to convert the RSTR object to an IClaimsIdentity. Unfortunately this requires a bit of XML parsing. Talk about a pain. Helper class it is:
public static class TokenHandler
{
private static XNamespace ASSERTION_NAMESPACE
= "urn:oasis:names:tc:SAML:1.0:assertion";
private const string CLAIM_VALUE_TYPE
= "http://www.w3.org/2001/XMLSchema#string"; // bit of a hack
public static IClaimsPrincipal Convert(RequestSecurityTokenResponse rstr)
{
return new ClaimsPrincipal(GetClaimsIdentity(rstr));
}
private static ClaimsIdentity GetClaimsIdentity(RequestSecurityTokenResponse rstr)
{
XDocument responseDoc = XDocument.Parse(rstr.RequestedSecurityToken.RawToken);
XElement attStatement = responseDoc.Element(ASSERTION_NAMESPACE + "Assertion")
.Element(ASSERTION_NAMESPACE + "AttributeStatement");
var issuer = responseDoc.Root.Attribute("Issuer").Value;
ClaimCollection claims = new ClaimCollection();
foreach (var c in attStatement.Elements(ASSERTION_NAMESPACE + "Attribute"))
{
string attrName = c.Attribute("AttributeName").Value;
string attrNamespace = c.Attribute("AttributeNamespace").Value;
string claimType = attrNamespace + "/" + attrName;
foreach (var val in c.Elements(ASSERTION_NAMESPACE + "AttributeValue"))
{
claims.Add(new Claim(issuer, issuer, claimType,
val.Value, CLAIM_VALUE_TYPE));
}
}
return new ClaimsIdentity(claims);
}
}
Most of this is just breaking apart the SAML-goo. Once I got all the SAML assertions I generated a claim for each one and created a ClaimsIdentity object. This gets me a step closer to how I wanted things, but keeping the identity around within the application is still up in the air. How can I keep the identity for the lifetime of the application? I wanted something like Thread.CurrentPrincipal but the phone platform doesn’t let you access it.
There was a class, TokenCache, that was part of the original Silverlight project. This sounded useful. it turns out it’s Get/Add wrapper for a Dictionary<>. It’s almost useful, but I want to be able to access this cache at any time. A singleton sort of solves the problem, so lets try that. I added this within the TokenCache class:
public static TokenCache Cache
{
get
{
if (_cache != null)
return _cache;
lock (_sync)
{
_cache = new TokenCache();
}
return _cache;
}
}
private static TokenCache _cache;
private static object _sync = new object();
now I can theoretically get access to the tokens at any time, but I want to make the access part of the base Application object. I created a static class called ApplicationExtensions:
public static class ApplicationExtensions
{
public static IClaimsPrincipal
GetPrincipal(this Application app, string appliesTo)
{
if (!TokenCache.Cache.HasTokenInCache(appliesTo))
throw new ArgumentException("Token cannot be found to generate principal.");
return TokenHandler.Convert(TokenCache.Cache.GetTokenFromCache(appliesTo));
}
public static RequestSecurityTokenResponse
GetPrincipalToken(this Application app, string appliesTo)
{
return TokenCache.Cache.GetTokenFromCache(appliesTo);
}
public static void
SetPrincipal(this Application app, RequestSecurityTokenResponse rstr)
{
TokenCache.Cache.AddTokenToCache(rstr.AppliesTo.ToString(), rstr);
}
}
It adds three extension methods to the base Application object. Now it’s sort of like Thread.CurrentPrincipal.
How does this work? When the RSTR is returned I can call:
Application.Current.SetPrincipal(rstr);
Accessing the identity is two-part.
If I just want to get the identity and it’s claims I can call:
var principal = Application.Current.GetPrincipal("https://troymcclure/webapplication3/");
IClaimsIdentity ident = principal.Identity as IClaimsIdentity;
If I want to reuse the token as part of web service call I can get the token via:
var token = Application.Current.GetPrincipalToken(https://troymcclure/webapplication3/);
There is still quite a lot to do in order for this to be production ready code, but it does a pretty good job of solving all the problems I had with domain authentication on the Windows Phone 7 platform.