Thursday 21 February 2008

SAML token serialization

So, as promised, my first post is regarding simple serialization/de-serialization of a SAML token.





The driver for this exercise was to implement the 'Renew' verb of the WS-Trust specification, using the framework that WCF provides. To my endless frustration, the development team over at Microsoft stopped short of implementing the entire WS-Trust spec for anything but SCTs! Instead we're left with just 'Issue'.





My STS is signing tokens using self-issued X509 certificates (one for the STS and one for each client). Here's the (shortened) code for the serialization of the token:




///
/// Write the given token into an XmlWriter object
///

///
///
public virtual void WriteToken(SamlSecurityToken token, XmlWriter writer)
{
System.ServiceModel.Security.WSSecurityTokenSerializer serializer = new System.ServiceModel.Security.WSSecurityTokenSerializer();
serializer.WriteToken(writer, token);
}


Now, when I receive the token back from the client for renewal I need to de-serialize it in order to update its validity time span. Here's the code for this:



///
/// Read the token from an XmlDictionaryReader reader
///

///
///
public virtual SamlSecurityToken ReadToken(XmlDictionaryReader reader)
{
System.ServiceModel.Security.WSSecurityTokenSerializer serializer = new System.ServiceModel.Security.WSSecurityTokenSerializer();
System.Collections.Generic.List tokens = new System.Collections.Generic.List();
tokens.Add(SigningToken);
tokens.Add(UnencryptingToken);
System.IdentityModel.Selectors.SecurityTokenResolver resolver =
System.IdentityModel.Selectors.SecurityTokenResolver.CreateDefaultSecurityTokenResolver(tokens.AsReadOnly(), false);
SamlAssertion assertion = new SamlAssertion();
assertion.ReadXml(reader, new SamlSerializer(), serializer, resolver);
return new SamlSecurityToken(assertion);
}



Note that here the signing token is the certificate used by the STS to sign the assertion, and the unencrypting token is the private key equivalent of the certificate used to encrypt the proof key in the RSTR.

The point here is that in order to de-serialize the token, you're going to need the private key of the certificate used to encrypt the original. I guess this isn't a problem when you're in control of client certification, but I think you can see why this might cause issues.

No comments: