Introduction

I came across to WCF 4 routing features while designing
some Central services which will provide various services to all of my client-end
service. I like to create a single entry point to communicate all those service
and keep them separate because of scalability reason. WCF routing feature seems
to me very exciting which support
for a configurable routing service that you can use in your WCF solutions.
Provides features for content-based routing, protocol bridging, and error
handling. But I have faced some issues
there while defining their security context in Routing service environment.

Background

Now a days I am building such architecture where ‘Service L’ in customer domain end will
provide some services to Client X, Y , Z
and so on.. workstations. ‘Service L’
has lots of things to provide its clients (like data from databases etc...
etc...).

And the interesting thing is that in some cases it will consume some
services from the Provider End which have been distributed in several
independent backend services like ‘Service
A’, ‘Service B’. Since those
services in Provider domain in not available outside, it has a routing service ‘Router service’ that gives all ‘Service L’ Clients to access the backend
services and it act like a bridge to consume them. So all ‘Service L’ going to become as a client to Routing service who send request to it over the internet and it going to route them to appropriate backend
service based on filter/policy.

The security between Service
L and Client X/Y/ Z has already
been established and I am not going to talk on that part so. I am very much concern
about rest of part I have, the security in the routing environment.

This routing part has been developed based on WCF 4.0 routing
feature. But I didn’t find any good solution for the security context when
forwarding the messages to back end services.

Transport-level and
message-level security

WCF allows us to enable security at two levels: the
transport level or the message level. Let me explain the difference between
these two levels here:

If we use
transport-level security then the complete communication (all the information
exchanged between the client and the server) would be encrypted.

If we use
message-level security then only the content of the SOAP
message is encrypted, while the rest of the SOAP message is left unencrypted.

So in configuration file while writing your binding configuration:

Using Security mode=Message means the message (or
parts of it) are encrypted and signed and can be sent over unsecured
transports.

Using Security mode=Transport means that the
communication channel is encrypted rather than just the message.

Transport is faster but means the data is only secure while on the wire
- if you had to use intermediaries (like the WCF 4 routing service) then it would
be able to see the message in the clear - with message security the message is
secure from sender to the receiver. Transport-level and message-level
security can assurance isolation, reliability, and certification. However, not
all communications need to have those three features all at once. Security is
usually desirable, but can be disabled. Encryption can also be activated to
ensure privacy.

Why
Not Transport Security?!!

WCF routing is based on message level rather than transport layer routing. Therefore, authentication at transport layer cannot be forwarded correctly by the router and there hasn't a direct means to make those security assertion flows from client to back end (bypass the Router Service). HTTPS/SSL like transport layer solution which can be used only for point to point rather than end to end case. So you cannot establish HTTPS/SSL connection across multiple nodes (client, router and server)

Here the routing service
like Consumer --> Routing Service --> Backend
Service, than I need to make sure that there is transport security enabled between

Consumer -> Routing Service

Routing Service -> Backend
Service

According to that, the message will be encrypted on transport from the consumer to the routing service. When the message enters the routing service it will be decrypted,
when sending the message to the back end service it will be encrypted again on transport and decrypted at the backend service. So the message will be encrypted
and decrypted twice in such solution. But Since There is intermediary systems between client and the service; each intermediate point must forward the message over a new SSL connection.
So Transport security is not appropriate when:

you are sending a message directly from your application to a WCF service and the message will not be routed through intermediate systems

Both the service and the client are located other than an intranet.

So I am going to avoid Transport security in my scenario.

Why Not Message Security?!!

Message
security is transport-independent and therefore can be used with any transport
protocol. When you use message based security this is done on the SOAP
message (so the encryption takes place on service level instead of transport
level) which gives an End-to-End security solution. So the consumer sends
an encrypted message (header is not encrypted default) and the Routing
Service just routes the encrypted message to the backend service and the
backend service decrypts the message. . So message security directly encrypts
and signs the message, having intermediaries does not break the security. But Message
based security gives you a performance penalty in comparison to Transport
Security, because the message becomes way larger after encrypting it.

So message security with Windows
credentials in Router and backend service will work since support of delegation
(Kerberos). And Client needs the access to that identity object. On the other
hand, it doesn’t also allow me to
forward security context for:

Username
and Password

X.509

Federated
credentials

It
means that the router can be configured to enforce message security but the
service must be configured to disable security and it cannot access the
security context such as the user's Identity.

So, What I am going to Do

Add extension of endpoint behavior to add headers to send User name and password (Can be send in encrypted way too).

Create a custom binding to encrypt and compression message in between Client and Routing Service.

Use Regular security in binding while forwarding message to back-end service from Routing service.

Create an authentication manager to do authentication by user name and password (against database) to avoid anonymous calls.

Add extension of endpoint behavior to add headers to send User name and password

Create a custom binding to encrypt and compression message in between Client and Routing Service

To compress the message over the wire I have used the Gzip from the sample provided by Microsoft. And i did some changes to add code for Encryption/Decryption there. So here I am going to highlight those portion of code:

So In both end , client and routing service end, I need to encrypt the data first and then compress it while send the data acrosse wire:

Cryptographer class which is responsible to encrypt and decrypt data here. I keep all these Gzip and Encryption stuff in GlobalCommonLib
assembly and here is the look of defining custom binding in my client side configuration file -

Here I have highlighted the portion of the custom binding definition. I have used httpTransport to enable sending/receiving data over HTTP which has been used in between
Client and Routing service here.

In Routing service configuration File, use the same configuration there. Take a look into the service endpoint
definition:

For this I have extend the ServiceAuthenticationManager and You need to configured this custom authentication manager in your configuration file.
In the Authenticate method I have retrieve the headers of username and password which I have sent earlier while sending request to routing service.
Router has forward that message to the backend service and here in backend service I can
retrieve those stuff and do authentication against any database.

Share

About the Author

"In my childhood, my uncle has shown me how to see the cloud in a close look and I understand that one can draw some elements of the Earth in the sky-canvas if he/she wants to. After that the cloud becomes closer to me and It teaches me one thing that, a deeper-look to something will give you some clues to draw your imagination. You can able to see that one which you have build-up in your mind.

Years past, I have started my career as a software engineer and has been looking for passion in my coding and development which I should be to enjoy my profession and has started asking myself- 'am I doing any engineering here?!' Is my code becoming that thing which I have designed in my mind? So to find that answer I have tried that old solution here... I have decided to come closer to my code and start analyzing them. And it is really working for me and at least it gives me the confidence that I can build something that I really want to. I can draw my thinking there through my code and can build-up my vision that I have designed in my mind. It also helps me to think out of the box, solve each problems by making blocks and make me careful on each steps." ----- says Morshed Anwar.

• Morshed's Technical Blog site: http://morshedanwar.wordpress.com/

• Morshed's Technical articles those are published in Codeproject site: http://www.codeproject.com/script/Articles/MemberArticles.aspx?amid=2992452

• Morshed's Linkedin profile: http://www.linkedin.com/in/morshedanwar

• Morshed's Facebook Profile : http://www.facebook.com/morshed.pulok

Beside all these Morshed like to do - photography and music. Here is Morshed's Flickr photos : http://www.flickr.com/photos/morshed_anwar/

Comments and Discussions

I have a scenario where WCF clients are on PC's that are networked, but no internet access. So I need to send WCF calls via a server on the network that does have internet access...

I had thought to use WCF router, but it doesn't seem to support username authentication. Your solution gets around that, but I wasn't sure if there were limitations regarding where the router needed to be

Yes offcourse. If your router can communicate with backend services from client-end, surely you can. Idont know your exact architechture, but You also can think of multiple router and do some experiments here.