WWSAPI to WCF interop 5: WSFederationHttpBinding with mixed mode security
WCF endpoints with WSFederationHttpBinding accept SAML tokens issued by trusted Security Token Services (STS, the Issuing Party, or IP). The first thing that should be noted with WSFederationHttpBinding is that secure conversation (specifically, the February 2005 version) is turned on and no knob is provided to turn it off (in fact, this is the case for WS2007FederationHttpBinding in .NET 3.5 as well). WSFederationHttpBinding has three security modes: None, Message, TransportWithMessageCredential. In Win7, WWSAPI will only provide support compatible to the TransportWithMessageCredential mode.
First of all, in order to send a SAML token, the client has to obtain such a token. For a WCF client using WSFederationHttpBinding, this happens automatically as the client will follow the STS endpoint specified in the binding to retrieve the SAML token. When there are multiple STS’s, the WCF client actually automagically unwinds the trust chain. In contrast, WWSAPI intentionally does not provide such magic. Instead, an API named WsRequestSecurityToken is provided for the client to call to get the token from the STS. Details of how to use WsRequestSecurityToken will be discussed in a later post. For the purpose of this post, we just need to know that the client has to call WsRequestSecurityToken (possibly multiple times) to get a token before building a proxy or channel to communicate with the WCF service endpoint (the Relying Party, or RP). The token returned from WsRequestSecurityToken is an opaque WWSAPI handle, WS_SECURITY_TOKEN.
The WS_SECURITY_TOKEN will be used in the WS_XML_TOKEN_MESSAGE_SECURITY_BINDING to represent the message credential. In addition to WS_XML_TOKEN_MESSAGE_SECURITY_BINDING, we need WS_SSL_TRANSPORT_SECURITY_BINDING in order to build the security description that matches the TransportWithMessageCredential mode in WSFederationHttpBinding. The following code shows how to do this.
WS_SECURITY_TOKEN* securityToken = NULL;
// call WsRequestSecurityToken to retrieve the security token
// e.g. WsRequestSecurityToken(channel, NULL, 0, &securityToken, NULL, error);
// declare and initialize an XML security token message security binding
WS_XML_TOKEN_MESSAGE_SECURITY_BINDING xmlTokenBinding = {}; // zero out the struct
xmlTokenBinding.binding.bindingType = WS_XML_TOKEN_MESSAGE_SECURITY_BINDING_TYPE; // set the binding type
xmlTokenBinding.bindingUsage = WS_SUPPORTING_MESSAGE_SECURITY_USAGE; // set the binding usage
xmlTokenBinding.xmlToken = securityToken; // securityToken returned from WsRequestSecurityToken
// declare and initialize an SSL transport security binding
WS_SSL_TRANSPORT_SECURITY_BINDING sslBinding = {}; // zero out the struct
sslBinding.binding.bindingType = WS_SSL_TRANSPORT_SECURITY_BINDING_TYPE; // set the binding type
// declare and initialize the array of all security bindings
WS_SECURITY_BINDING* bootstrapSecurityBindings[2] = { &sslBinding.binding, &xmlTokenBinding.binding };
// declare and initialize the security description
WS_SECURITY_DESCRIPTION bootstrapSecurityDescription = {}; // zero out the struct
bootstrapSecurityDescription.securityBindings = bootstrapSecurityBindings;
bootstrapSecurityDescription.securityBindingCount = WsCountOf(bootstrapSecurityBindings);
Now this security description won’t work with a WCF endpoint using WsFederationHttpBinding. Why? We need secure conversation. As noted earlier, secure conversation is required in WSFederationHttpBinding, so the WWSAPI client has to use the WS_SECURITY_CONTEXT_MESSAGE_SECURITY_BINDING to describe how to use secure conversation (version, entropy mode, etc.). If you are familiar with the WS-SecureConversation spec, you know that the original client credential is used to negotiate a session key, which is used for future client authentication. In the WWSAPI design, the initial negotiation using the client credential (the SAML token here) is called bootstrapping. A separate channel is created to do this negotiation, which needs to be described in a different security description. This is exactly what the code above gives you (notice the word “bootstrap” in the variable name?). Now if you look into the WS_SECURITY_CONTEXT_MESSAGE_SECURITY_BINDING, you will know how to hook this up.
// declare and initialize a secure conversation message security binding
WS_SECURITY_CONTEXT_MESSAGE_SECURITY_BINDING contextBinding = {}; // zero out the struct
contextBinding.binding.bindingType = WS_SECURITY_CONTEXT_MESSAGE_SECURITY_BINDING_TYPE;
contextBinding.bindingUsage = WS_SUPPORTING_MESSAGE_SECURITY_USAGE;
contextBinding.bootstrapSecurityDescription = &bootstrapSecurityDescription;
// declare and initialize the array of all security bindings
WS_SECURITY_BINDING* securityBindings[2] = {&contextBinding.binding, &sslBinding.binding};
// declare and initialize the security description
WS_SECURITY_DESCRIPTION securityDescription = {}; // zero out the struct
securityDescription.securityBindings = securityBindings;
securityDescription.securityBindingCount = WsCountOf(securityBindings);
Please note that in the code above we reuse the sslBinding used in the bootstrap security description. This is necessary because WWSAPI requires the transport security used for protecting the secure conversation to be same as the one initially used to negotiate the session key. This requirement simplifies the design as well as the usage pattern. Of course you don’t have to use the same variable. As long as the binding type and settings match, it is ok.
Note: the corresponding WSFederationHttpBinding object can be created by new WSFederationHttpBinding(WSFederationHttpSecurityMode.TransportWithMessageCredential). It is represented in the following element in config:
<wsFederationHttpBinding>
<binding name="federation">
<security mode="TransportWithMessageCredential">
<message>
<issuer address="https://localhost:8443/FederationSample/BookStoreSTS/wsHttps"
binding="wsHttpBinding" bindingConfiguration="UPOverHttps" />
</message>
</security>
</binding>
</wsFederationHttpBinding>
Comments
Anonymous
November 24, 2008
PingBack from http://blog.a-foton.ru/index.php/2008/11/24/wwsapi-to-wcf-interop-5-wsfederationhttpbinding-with-mixed-mode-security/Anonymous
April 06, 2009
Below you may links to resources available for connecting C/C++ code and Web Services using Windows WebAnonymous
May 15, 2009
In my post on WWSAPI federation support , I explained how to set up secure conversation on the WWSAPI