This would hopefully be a multi-part series showing some tricks to enable claims-based-security in Silverlight 4.0. Silverlight 5.0 would have a much better story around claim-based-security as mentioned here.

In this first post, I’ll give you a high level overview of the solution. The main idea is to use the ‘WCF Routing Service’ in the DMZ to route both token issuance requests & business requests to the actual backend services.

1. Routing Service looks for a token issuing request and forwards it to the STS where the actual authentication is performed. After the successful authentication, STS issues a SAML token which goes back to Silverlight client via the routing service. Routing Service also terminates the SSL and backend is called using straight HTTP. This model offers strong security on the internet while keeping the internal deployment simpler & efficient. This model also resembles with the standard SSL offloading setup where a hardware load-balancer is used to terminate the SSL.

1: Token Issuance Path

image

2. Once the Silverlight client got a SAML token, it can attach it to all subsequent message sent to business service(s). Routing Services forwards al the business messages (messages which doesn’t match the token issuance filter) to the actual backend services again doing the protocol transitioning from HTTPS to HTTP. Please note, here you can use the rich filtering mechanism provided by the Routing services to decide which messages should to which services. I used a very simple MatchAll filter which forwards all the non-token-issuance messages to the business service.

2: Web Service Call Containing a SAML Token

image

To implement the 1st part of solution I have used the WSTrustClient class & the associated bindings from the identity training kit.

var vm = this.DataContext as MainPageViewModel;

var stsBinding = new WSTrustBindingUsernameMixed();

var stsCreds = new UsernameCredentials(vm.UserId, vm.Password);
var client = new WSTrustClient(
    stsBinding,
    new EndpointAddress(vm.SelectedEndpoint),
    stsCreds);

var rst = new RequestSecurityToken(WSTrust13Constants.KeyTypes.Bearer);
rst.AppliesTo = new EndpointAddress(vm.AppliesTo);

client.IssueCompleted += new System.EventHandler<IssueCompletedEventArgs>(client_IssueCompleted);
client.IssueAsync(rst);

For the 2nd part I have implemented a message inspector along with an extension method which makes it super easy to attach the SAML with outgoing messages.

var vm = this.DataContext as MainPageViewModel;
var client = new ServiceReference1.Service1Client();

client.AttachToken(vm.SecurityToken.RawToken);

client.GetDataCompleted += new EventHandler<ServiceReference1.GetDataCompletedEventArgs>(client_GetDataCompleted);
client.GetDataAsync(32);