Let's consider our organization as a financial type of organization where we have different applications and services to help the employees carrying out their activities. One such users are traders. They execute trades which are then forwarded to any specific exchange for placement. We need to make sure that only traders are allowed to execute trade. One such way is to check at the service level if the requester is a trader and allow the operation only under such case.
In WCF scenarios for a Windows Active Directory based domains, users belong to different domain groups. These groups are used by applications to determine the user privileges before executing the actual operation. The same approach has been traditionally taken to implement security for our services. This is exactly what we would be trying to discuss in this post. For our organization, let us assume that all traders belong to Traders group.
Let's start by creating a WCF Service Library project, TradeExecutionServiceLib.

Now let's update the name of the service contract and the implementation to ITradeExecutor and TradeExecutor respectively. Doing it on the solution explorer level would ensure that the class names are updated inside their respective files. This should also update the service configuration in App.Config file.

Now let us update ITradeExecutor as follows:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace TradeExecutionServiceLib | |
{ | |
using System.ServiceModel; | |
[ServiceContract] | |
public interface ITradeExecutor | |
{ | |
[OperationContract] | |
void ExecuteTrade(string symbol, int quantity); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace WcfServiceLibrary1 | |
{ | |
using System; | |
using System.Security.Permissions; | |
public class TradeExecutor : ITradeExecutor | |
{ | |
public void ExecuteTrade(string symbol, int quantity) | |
{ | |
Console.WriteLine(symbol); | |
Console.WriteLine(quantity); | |
} | |
} | |
} |
Decorating Service Operations with PrincipalPermissionAttribute
One way to authorize user's role is to decorate the operation with PrincipalPermissionAttribute. Here Role would mean the Windows group we are specifically looking for. Now this becomes the responsibility of runtime hosting the service to ensure that the user of the service is a member of the specified group and deny access otherwise.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[PrincipalPermission(SecurityAction.Demand, Role = @"CHEETA\Traders")] | |
public void ExecuteTrade(string symbol, int quantity) | |
{ | |
Console.WriteLine(symbol); | |
Console.WriteLine(quantity); | |
} |

If you double click the icon on the tray, you should see that service is hosted and the status should show as Started.

This should also launch WCF Test Client with the operations listed on the service.

Let us provide the input arguments for ExecuteTrade operation and hit Invoke. Since were debugging it, we should be able to see the following security exception in the visual studio editor:

If you continue the execution then you should see the following on the WCF Test Client side which just shows the client that there is something wrong with the request. When we write our custom clients we should be handling this case more gracefully showing the user the exact cause of the error or how to request permissions if he is a legitimate user of the service.

Since the service operation requires the user to belong to a certain role, it blows up as there is no such membership for the requesting user. Not even such a group exists on the machine [CHEETA]. To keep it simple, let us create a Windows Group using the Computer Management tool as follows:

Let's add the user (requester) to the Traders group now. See the highlighted information requiring the user to login again in order for the changes to take effect.

Now let us update ServiceModel section of the service configuration in App.Config to use Windows security. Here we have updated the binding to net TCP. We have also updated authorization behavior use Windows Accounts.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<system.serviceModel> | |
<services> | |
<service name="TradeExecutionServiceLib.TradeExecutor"> | |
<endpoint address="" binding="netTcpBinding" | |
contract="TradeExecutionServiceLib.ITradeExecutor"> | |
<identity> | |
<dns value="localhost" /> | |
</identity> | |
</endpoint> | |
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" /> | |
<host> | |
<baseAddresses> | |
<add baseAddress="net.tcp://localhost:8733/TradeExecutionServiceLib/TradeExecutor/" /> | |
</baseAddresses> | |
</host> | |
</service> | |
</services> | |
<behaviors> | |
<serviceBehaviors> | |
<behavior> | |
<serviceMetadata /> | |
<serviceAuthorization principalPermissionMode="UseWindowsGroups" /> | |
<serviceDebug includeExceptionDetailInFaults="False" /> | |
</behavior> | |
</serviceBehaviors> | |
</behaviors> | |
</system.serviceModel> |

The class hierarchy of PrinicipalPermissionAttribute is as follows:

Non-Declarative Permission Demands
In the above example we provided the required membership requirements by adding PrinicipalPermissionAttribute to the operation contract implementation. The same behavior can be achieved by doing the same thing in the code. The unauthorized access would be determined by WCF Service pipeline and an exception would be generated which would result in a fault for the user. In the below code, we are just updating the code to demand membership using the same Principal Permission, but using code.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public void ExecuteTrade(string symbol, int quantity) | |
{ | |
var permission = new PrincipalPermission(null, @"CHEETA\Traders"); | |
permission.Demand(); | |
Console.WriteLine(symbol); | |
Console.WriteLine(quantity); | |
} |
The definition of PrincipalPermission is as follows:

If we look at the definition of PrincipalPermissionAttribute, it is using the same IPermission.

Download Code
3 comments:
Thnks :)
Excellent Post.........Thanks MUHAMMAD...Keep Posting
Excellent Post.......Thanks MUHAMMAD
Keep Posting
Post a Comment