understanding “asymmetric” proof tokens in SAML/ws-trust

We rebuilt the WCF sample for “Federation” so it works under IIS express, with SSL endpoint, and can be debugged. This required changing lots of URIs, bindings, etc. But, we can now run our winforms client, talking to a service hosted in IIS express (user mode), whose federated bindings (server edition) induces the client’s proxy to go talk (backwards speaking) to a STS called  bookstore STS – an RP sts role entity – and then HomeRealmSTS (an IP-role entity). Of course, in practice the client first sends its RST to HomeRealmSTS.

Note we set the ws-security default binding on the WCF service so that we have removed all “windows” centric defaults. The binding security mode is transport (i.e. https), and the transport’s message type is NONE (vs. windows).


we see the HomeRealm STS’s request handler kick in, where we note that the client has sized the proof key but not supplied any entropy (in code, but note the wire below). As a result, all bytes are computed using the “random number” generator of dotNet.


The net result is a SAML assertion, with HOK confirmation fields – an RSAOAEP-wrapped key


Obviously, this per-recipient (think MSP from NSA) is just of many that might now be attached, for each of the potential consumers of this assertion.

For the original client (proxy), ws-trust provides the cleartext:


Presumably, the means of invoking the proof service using these now exchanged keys is the same as with symmetric HOK – keyed hashes.

We see the shared key is rsa-encrypted for the next sts – that acts as a key-translation entity (obviously), re-encrypting it (presumably under RSA vs. symmetric key wrapping) for the servicecert of the eventual service provider.l


now the trick is to simplify the setup so we avoid the wsfederationhttpbinding’s various “features”. We just want the basic WCF client-side ws-trust code to call the “proof-token capable” STS, with normal (non SCT-related) parameters

                    string baseUri = "https://me:44305/FederationSample/HomeRealmSTS/STS.svc";

                    //Limited edition of WSTrustClient:)
                    IssuedSecurityTokenProvider provider = new IssuedSecurityTokenProvider();
                    provider.SecurityTokenSerializer = new WSSecurityTokenSerializer();

                    //Relying Party's identifier
                    provider.TargetAddress = new EndpointAddress(new Uri("https://foo.com/"));
                    provider.IssuerAddress = new EndpointAddress(new Uri(baseUri));

                    provider.SecurityAlgorithmSuite = SecurityAlgorithmSuite.Basic256;
                    provider.MessageSecurityVersion = MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10;

                    HttpsTransportBindingElement tbe = new HttpsTransportBindingElement();
                    tbe.AuthenticationScheme = AuthenticationSchemes.Negotiate;
                    CustomBinding stsBinding = new CustomBinding(tbe);

                    provider.IssuerBinding = stsBinding;
                    //Request a token from ADFS STS
                    SecurityToken issuedToken = provider.GetToken(TimeSpan.FromSeconds(30));
                    var samlt = issuedToken as GenericXmlSecurityToken;

                    SecurityTokenHandlerCollection collection = SecurityTokenHandlerCollection.CreateDefaultSecurityTokenHandlerCollection();

                    var cert = LookupCertificate(ServiceConstants.CertStoreName, ServiceConstants.CertStoreLocation, "CN=HomeRealmSTS.com");
                    List<SecurityToken> l = new List<SecurityToken>();
                    l.Add(new X509SecurityToken(cert));

                    SecurityTokenResolver AcsIssuerResolver = SecurityTokenResolver.CreateDefaultSecurityTokenResolver(l.AsReadOnly(), false);
                    collection.Configuration.IssuerTokenResolver = AcsIssuerResolver;
                    collection.Configuration.ServiceTokenResolver = AcsIssuerResolver;

                    collection.Configuration.AudienceRestriction.AudienceMode = AudienceUriMode.Never;

                    IClaimsIdentity claimsIdentity = null;
                    using (var reader = XmlReader.Create(new StringReader(samlt.TokenXml.OuterXml)))
                        SamlSecurityToken samltoken = collection.ReadToken(reader) as SamlSecurityToken;



About home_pw

Computer Programmer who often does network administration with focus on security servers. Sometimes plays at slot machine programming.
This entry was posted in SAML. Bookmark the permalink.