Friday 28 March 2008

Federation over a Duplex channel

Me again.

This time I wanted to do something a little beyond the norm, at least as far as the available examples are concerned. I would really like to implement a publish/subscriber service, where an application subscribes to various system wide events. Seems like a job for a Duplex channel - the client subscribes to service, and also provides an endpoint as a means to receive events.

The big catch here is that I'd love this service to execute under the same security context as the rest of my architecture, i.e. I'd like the service to be federated with my STS.

After trawling the net, I found several useful snippets, but nothing that solved the whole problem. Specifically, I wanted to achieve all this via config, if possible.

So here's how I did it...


The client binding looks like

<customBinding>
<binding name="DuplexBinding">
<security authenticationMode="SecureConversation">
<secureConversationBootstrap authenticationMode="IssuedToken">
<issuedTokenParameters tokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1">
<issuer address="http://localhost:8080/STS/Slave" binding="wsFederationHttpBinding" bindingConfiguration="UserNameFederationBinding">
<identity>
<dns value="My STS" />
</identity>
</issuer>
<issuerMetadata address="http://localhost:8080/STS/Slave/mex" />
</issuedTokenParameters>
</secureConversationBootstrap>
</security>
<compositeDuplex clientBaseAddress="http://localhost:8080/Client"/>
<oneWay/>
<textMessageEncoding />
<httpTransport />
</binding>
</customBinding>

Here, the original authentication mechanism was via a Username token. Notice the order of the elements within the tag - this foxed me for a good while before it clicked! Also note that the authentication mode is set to 'SecureConversation', with the bootstrap mode set to 'IssuedToken'. Initially I thought this seemed counter-intuitive, but when you consider the order in which WCF (or more correctly, WS-Security) performs its negotiation, this makes more sense.

In the service, the binding looks like

<customBinding>
<binding name="DuplexBinding">
<security authenticationMode="SecureConversation">
<secureConversationBootstrap authenticationMode="IssuedToken">
<issuedTokenParameters tokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1">
<issuer address="http://localhost:8080/STS/Slave" binding="wsHttpBinding" />
<issuerMetadata address="http://localhost:8080/STS/Slave/mex" />
</issuedTokenParameters>
</secureConversationBootstrap>
</security>
<compositeDuplex/>
<oneWay/>
<textMessageEncoding />
<httpTransport />
</binding>
</customBinding>

The service works in exactly the same way a standard Duplex service would, i.e. it simply retains a reference to the callback channel, like so

IRegisterCallback callback = OperationContext.Current.GetCallbackChannel();

in order to use this when necessary.

I hope this helps anybody else wishing to do the same, or similar, with their architecture.

Cheers

Graeme