Windows Cardspace Meets Vista Media Center

It's again time to post a new blog entry. This time I thought it may be interesting to see how Windows Cardspace can be used together with applications built on top of the Media Center Presentation Layer (WMCPL). So and why do I think that Cardspace can be of very good use especially in a Media Center scenario? The answer is pretty straight forward because Cardspace not only enables you to manage information (claims) about you in an efficient and transparent way it also allows you to do this without necessarily using your keyboard.

No think of Media Center. Media Center is targeted to be used in a living-room in a leaned back scenario to provide what we call a 10-foot experience. So rarely will you have a keyboard at hand when it comes to the use of Media Center applications that require registration or authentication or more broadly spoken any sort of information about you. And when talking to customers we encourage application developers not to rely on the keyboard at all but only on the remote control.

So now I think it becomes clear that Windows Cardspace either with managed cards or even self issued cards could offer a great benefit to the user and the relying parties. So that's why I tried to have Windows Cardspace working in a simple WMCPL application. So here's what I did and what the issues were.

First of all I thought it would all be pretty much straight forward, create a Windows Communication Foundation Service using a Separation with the configuration representing my infrastructure (eg. certificates, etc.), deploy the service, start-up Visual Studio 2008 and use the great feature of "Add a Service Reference" which configures all the client side configuration stuff for you and then wire some UI up to visualize some meaningful data extracted from the security token. Sounds easy however there is on little roadblock in the scenario that doesn't make things that easy and that is that a WMCPL media center application is executed in a special media center runtime container and is deployed as a DLL which is executed by this runtime process called "ehexthost.exe". Therefore you cannot simply provide an app.config file with all the WCF/Cardspace stuff in it with your DLL as it will not be picked up by the runtime. So you better be off providing the configuration in code which is also not very difficult but it is more effort to do. However you could anyway let Visual Studio 2008 create the XML config for you and then you can use this as a template for transferring it into C# or VB.Net code. In my case the relevant code looks like this (without most of the optional binding attributes which are usually in the config when you create the service reference using Visual Studio):

WSFederationHttpBinding binding = new WSFederationHttpBinding(WSFederationHttpSecurityMode.Message);
binding.MessageEncoding = WSMessageEncoding.Text;
binding.TextEncoding = Encoding.UTF8;
binding.Security.Message.AlgorithmSuite = SecurityAlgorithmSuite.Default;
binding.Security.Message.IssuedKeyType = SecurityKeyType.SymmetricKey;
binding.Security.Message.IssuedTokenType = "urn:oasis:names:tc:SAML:1.0:assertion";
binding.Security.Message.NegotiateServiceCredential = false;

X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certs = store.Certificates.Find(X509FindType.FindByThumbprint, "92306aef4808fbe373d745b3b2759e1ae63e7e80", true);

store.Close();

EndpointIdentity identity = EndpointIdentity.CreateX509CertificateIdentity(certs[0]);

binding.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
binding.Security.Message.IssuerAddress = new EndpointAddress(new Uri("
https://schemas.xmlsoap.org/ws/2005/05/identity/issuer/self") , identity);
binding.Security.Message.ClaimTypeRequirements.Add(new System.ServiceModel.Security.Tokens.ClaimTypeRequirement("
https://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname" , false));
binding.Security.Message.ClaimTypeRequirements.Add(new System.ServiceModel.Security.Tokens.ClaimTypeRequirement("
https://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname" , false));
binding.Security.Message.ClaimTypeRequirements.Add(new System.ServiceModel.Security.Tokens.ClaimTypeRequirement("
https://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" , false));

X509Certificate2 cert = new X509Certificate2(Convert.FromBase64String("AwAAAAEAAAAUAAAAkjBq70gI++Nz10WzsnWeGuY+foAgAAAAAQAAACwEAAAwggQoMIICEKADAgECAgJDmzANBgkqhkiG9w0BAQUFADBUMRQwEgYDVQQKEwtDQWNlcnQgSW5jLjEeMBwGA1UECxMVaHR0cDovL3d3dy5DQWNlcnQub3JnMRwwGgYDVQQDExNDQWNlcnQgQ2xhc3MgMyBSb290MB4XDTA4MDIxMjA3NDg1MFoXDTEwMDIxMTA3NDg1MFowGTEXMBUGA1UEAxMOd3d3LmxldmVsNzAuZGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALDqOFljkQXyZWKFJQYlsyxhw2Rh4fzUM+pokB6oPMJxMO7iJ+NywbHHv1HAu8mnDIV2dj+CvFoLuOT8dJs5Kn2WiG3Uv+gJ9yey6WRjkJoqXGRWJUqwzErCiIfee6jImQWd0h06zs0pIipoCncuBY4uhzgEs1rDyF2Xkjx93gNDAgMBAAGjgcIwgb8wDAYDVR0TAQH/BAIwADA0BgNVHSUELTArBggrBgEFBQcDAgYIKwYBBQUHAwEGCWCGSAGG+EIEAQYKKwYBBAGCNwoDAzALBgNVHQ8EBAMCBaAwMwYIKwYBBQUHAQEEJzAlMCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5jYWNlcnQub3JnLzA3BgNVHREEMDAugg53d3cubGV2ZWw3MC5kZaAcBggrBgEFBQcIBaAQDA53d3cubGV2ZWw3MC5kZTANBgkqhkiG9w0BAQUFAAOCAgEAmYo394ooJgOwe+RpYvR/0ouAJWwP4wqK7TkQu9DXHJZuAZ+nWk42jg+WQkzeGNauVQcbh9fOfKv6Jk0w/99r11JUMu9eFNk4wmGxQ4NeX/ad9e3MmUmHjSuTBtBXLrC0jnWEJV6En6tMguSGWpvtDcVuiccp1dHlGW2FnVqiwRtk2+S8ZJUMIGUtqu9ann9zhtp2sxat4C+3YGGlD89PKsyiKmIrK5YMGTSsd32l9MQar8MP03kSjXModysbvukgBWk4GqnfL+zB/AP6tB04u+ftm/PLCKEtWqRKbRkGkBkpfmaMAYNL61OQC4hSfXoh4Id9ijsWMS8XunBPnA6ydqQ3VsexLyndccADEt79i1zFV1ReWV0Q3EpsmSwqDtSmovwuoGhu6AUknA10efWeBv9RQspxuS1QBf67e7pSrh01DStQP09t+r9tHtmQMGEfu/oVDWd87zCoyHnqTl7A+UXnaOQMt8WCLHoDlprSbgyNqh5Lm+dJv+Av/4LQLdqzbCUOU4M/M1xvJTqjLbJ+Y7eJSNleRAruNG6HjnhH8FicTF/PCmOT4fo3ocBMTWTYeM8gz3Q/s2zvURZDax3cPQQpC2NTkEQjxpdT6B28u/G9YcJibyeurV8cM3l+2+SkwrTknTFjHuZ2tICuoUGAKlERKpWpjC0Q3DQPKBfKvfI="));

EndpointIdentity remoteIdentity = EndpointIdentity.CreateX509CertificateIdentity(cert);
EndpointAddress remoteAdress = new EndpointAddress(new Uri(" https://www.level70.de/MyService/Service1.svc") , remoteIdentity);

When you have done that you can use the proxy class that you generated with the WCF svcutil.exe to consume the respective service method. The only thing you have to remember is that you have to pass the binding object you created in the step above to the constructor of the proxy.

Service1Client sc = new Service1Client(binding, remoteAdress);

The service response can then be wired up with the UI of your media center application. In my case those are simple Text elements within a ColorFill which are wired up to properties in my application class which is derived from ModelItem to have the UI so that I don't have to care about notifying the UI when the property values change. The wiring is done in a Rule-Section for the respective UI like shown below:

<Rules>
<Binding Source="[Application.Name]" Target="[Label1.Content]"></Binding>
<Binding Source="[Application.FirstName]" Target="[Label2.Content]"></Binding>
<Binding Source="[Application.Mail]" Target="[Label3.Content]"></Binding>
</Rules>

Then you can deploy the application and enjoy using the Vista Media Center with Cardspace.

Click on the picture to get a larger view Click on the picture to get a larger view Click on the picture to get a larger view

You can see a Video of my sample application if you click on the image link below.

Play video in Silverlight Player

So you see that it is quite easy to integrate Infocard based authentication, authorization and identity claims exchange in the Vista Media Center which is surely of great benefit. However as tempting such a scenario seems to be there is one major hurdle if you plan to have your application added to the Microsoft Media Center Online Gallery as it will most probably not pass the application audit. And this is because the Cardspace Selector today is a two-foot window which represents a break in user experience in a Media Center 10-foot terms and therefore will most likely lead to a rejection of the app so that you must provide your own distribution strategy.

The only way to solve this issue would be to implement a Card Selector with a 10-foot UI and there are no plans by the Media Center team within Microsoft to do something like this. So you would be left on your own devices. While not impossible since the specs are there and publicly available here it is probably not feasible to do this for a single organization publishing an application. Another thing to mention in concerning this matter is that one of the design goals of Cardspae is to provide a consistent experience to the user when using Infocards and this goal would be pretty much violated if we would have an inflational increase in Card Selectors out there.