A more elegant way of embedding a SOAP security header in Silverlight 4
- by Your DisplayName here!
The current situation with Silverlight is, that there is no support for the WCF federation
binding. This means that all security token related interactions have to be done manually.
Requesting the token from an STS is not really the bad part, sending it along with
outgoing SOAP messages is what’s a little annoying. So far you had to wrap all calls
on the channel in an OperationContextScope wrapping an IContextChannel.
This “programming model” was a little disruptive (in addition to all the async stuff
that you are forced to do).
It seems that starting with SL4 there is more support for traditional WCF extensibility
points – especially IEndpointBehavior, IClientMessageInspector.
I never read somewhere that these are new features in SL4 – but I am pretty sure they
did not exist in SL3.
With the above mentioned interfaces at my disposal, I thought I have another go at
embedding a security header – and yeah – I managed to make the code much prettier
(and much less bizarre). Here’s the code for the behavior/inspector:
public class IssuedTokenHeaderInspector : IClientMessageInspector
{
RequestSecurityTokenResponse _rstr;
public IssuedTokenHeaderInspector(RequestSecurityTokenResponse rstr)
{
_rstr
= rstr;
}
public void AfterReceiveReply(ref Message reply, object correlationState)
{
}
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
request.Headers.Add(new IssuedTokenHeader(_rstr));
return null;
}
}
public class IssuedTokenHeaderBehavior : IEndpointBehavior
{
RequestSecurityTokenResponse _rstr;
public IssuedTokenHeaderBehavior(RequestSecurityTokenResponse rstr)
{
if (rstr
== null)
{
throw new ArgumentNullException();
}
_rstr
= rstr;
}
public void ApplyClientBehavior(
ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.MessageInspectors.Add(new IssuedTokenHeaderInspector(_rstr));
}
//
rest omitted
}
This allows to set up a proxy with an issued token header and you don’t have to worry anymore with embedding the header manually with every call:
var client
= GetWSTrustClient();
var rst
= new RequestSecurityToken(WSTrust13Constants.KeyTypes.Symmetric)
{
AppliesTo
= new EndpointAddress("https://rp/")
};
client.IssueCompleted += (s, args) =>
{
_proxy
= new StarterServiceContractClient();
_proxy.Endpoint.Behaviors.Add(new IssuedTokenHeaderBehavior(args.Result));
};
client.IssueAsync(rst);
Since SL4 also support the IExtension<T> interface, you can also
combine this with Nicholas Allen’s AutoHeaderExtension.