views:

292

answers:

3

I have a few services that are being consumed by clients within a secure zone. I've been asked to protect these services typically against development clients mistakenly connecting to the wrong service.

The idea was to pre-shared key (like a guid) which is set in the config for both the client and the service host. Whenever The client tries to consume the service it must present the correct key.

How would I go about configuring a service to implement this kind of security? How much customization is necessary?

A: 

If you do it using the key, you would change the contract of the service to include a field that the key would be placed in. Then check the value in the key on the server side.

However, in your case you could restrict which IP addresses were allowed to access the service, through the network configuration. This would be less work than changing the signature of your services.

Shiraz Bhaiji
This is not a good idea - that way, you have to change your contracts, and you "pollute" your actual business logic with infrastructure/steering fields. I would not recommend this approach.
marc_s
+2  A: 

I would have the client send the key as an extra message header and create a IDispatchMessageInspector to check for the header and optionally reject it. This Code Project article describes the filter part based on the IP address.

Maurice
Thank you, I like the look of this approach. I've done a bit of searching around this idea, and it looks like I should be using an IClientMessageInspector to insert the key on the client side - implemented as an endpoint behavior. And then on the server side I'll have a behavior that implements IDispatchMessageInspector that checks for the key.One last thing - is there anything readymade in wcf that would achieve a similar goal but without the need for a custom behavior?
Columbo
If you are not using the WCF security features you could use them for this approach. In that case I would create a certificate for each client app and in the each service check for the allowed client certificates. And I suppose you could do the same with username/password although that would force you to use HTTPS as well.
Maurice
Thanks, the user/pass authentication was something we'd considered before, but we had a few issues with the ssl and our network config that meant we started looking for other ways of meeting the requirement.From what I've learned today, I think I'll use this approach of sending a shared key in the header. So now it's just to make a little test project :)
Columbo
+2  A: 

You could easily add a custom message header to each call - pretty easy to do, actually, and it doesn't "pollute" your real service contract, e.g. you don't have to add extra parameters to your service calls just to pass this.

See these articles for info on how to achieve this:

Basically, you need to wrap your call to the service in a OperationContext - that's all, no ClientMessageInspector and other trickery needed :-)

 using (OperationContextScope scope = new OperationContextScope(proxy))
 {
     Guid myToken = Guid.NewGuid();

     MessageHeader<Guid> mhg = new MessageHeader<Guid>(myToken);
     MessageHeader untyped = mhg.GetUntypedHeader("token", "ns");

     OperationContext.Current.OutgoingMessageHeaders.Add(untyped);

     proxy.DoOperation(...);
  }

and on the server side, you can simply inspect the IncomingMessageHeaders collection:

Guid myToken = OperationContext.Current.
                 IncomingMessageHeaders.GetHeader<Guid>("token", "ns");

Marc

marc_s