Serializing/Deserializing the bootstrap token

Posted on Updated on

I’ve been doing some work with WCF and WIF. Yes this new foundation thing called Windows Identity Foundation.

If you have seen the PDC09 demos than you probably thought that it’s so easy to add security to an application… well yes and no. It’s easy if you only want the standard functionality out of the box, but if you need to do something different… it’s quite complicated to get everything working. However, once you understand what’s going on then it is a lot smoother and you don’t need to worry anymore about how it works, it just works.

The last tornado I had to deal with was the serialization of security tokens. You may want to know why you would want to serialize tokens if WIF does it for you adding them to cookies or WCF heathers. Well that’s like asking why you would generate plain HTML to add custom CSS when you can use ASP.Net controls that spit out heaps of formatted html with colors. In this case, my reason is that I wanted to be able to open a windows application from the web browser and keeping the credentials I had in the browser.

To do that, you need to serialize the token into a file and your browser opens the application associated to that extension. It’s like when you download an excel sheet and instead of saving the file you open it directly in Excel or the same with a PDF. But in our scenario, we send the information that WIF had put in a cookie to the windows app so that we can call some WCF services. Easy. Serialize that monster and you deserialize it in the client to create the Channel. Go for it. If you are reading this is because it wasn’t that easy, isn’t it? Then, try to deserialize it now that you managed to serialize it. Ha!!.

The Idea is that you serialise your bootstrap token into an XML string

var bootstrapToken = ((IClaimsPrincipal)Thread.CurrentPrincipal).Identities[0].BootstrapToken; 

// Serialize
var req = new SamlSecurityTokenRequirement();
var handler = new Saml11SecurityTokenHandler(req);
var sb = new StringBuilder();
using (var writer = XmlWriter.Create(sb))
   handler.WriteToken(writer, bootstrapToken);                   

string serializedToken = sb.ToString();

Serializarion is quite simple, but to deserialize the token we need to have the public key of the signing certificate because the classes that do the deserialization want to validate that moster. This sample shows how to read the certificate from a file, but the constructors allow reading from a stream (or you may want to serialize the x509 certificate together with the token in the file that you send to your win app).

// Deserialize
string path = @"c:\temp\STSPublic.cer";
// It can be deserialised from a byte[]
var cert = new X509Certificate2(path);
var token = new X509SecurityToken(cert);
var tokens = new List<SecurityToken>() {token}; 

var resolver = SecurityTokenResolver.CreateDefaultSecurityTokenResolver(tokens.AsReadOnly(), false);
var conf = new SecurityTokenHandlerConfiguration();
conf.IssuerTokenResolver = resolver;
handler.Configuration = conf; 

using (var reader = XmlReader.Create(new StringReader(sb.ToString())))
   bootstrapToken2 = handler.ReadToken(reader);

Instead of reading the certificate from a file you can read the certificate from the list of installed certificated from the local machine you can also use the following code.

var token = new X509SecurityToken(CertificateUtil.GetCertificate(StoreName.My, StoreLocation.LocalMachine, "CN=STSCertificateName"));

Now it’s up to you to do whatever you want with the token in the windows app.

I hope this helps.