Securing WCF Services: Preventing Unauthorized Access

Suppose you are writing a web service to perform a sensitive calculation. Your web service should only be accessible by authorized users and/or applications. Here’s my advice for configuring your service:

Use .NET to Your Advantage

.NET has built in features for ensuring that the code calling yours is authorized to do so. For example, take a look at this snippet of code:

[PrincipalPermission(SecurityAction.Demand, Role = "MyLocalSecurityGroup"]
public SearchResults Find(string contractNumber)
{
    ...
}

Notice the [PrinciplePermission] attribute. This attribute tells .NET that only principals who are members of the "MyLocalSecurityGroup" role are allowed to run this method (where a principal is a user/service account, and a role is a locally defined security group on the server). In other words, in order to run this method, the caller must be running under an account that is a member of the local security group specified.

Local Security Groups

By telling your code to check a security group on the local server, you get around the problem of having to care about the different test regions in your code. The local group on your DEV server will contain only those accounts which are authorized to access the service in DEV. Likewise, the TST and PRD local security groups will only contain accounts authorized to access TST and PRD respectively.

Domain Security Groups (NT Groups)

Of course, you don’t want to manage access at the local server level. Rather, you want to let User Account Services (UAS) manage access centrally. The way to do this is to create domain security groups for each test level. For the middleware, I created these groups.

  • MyDomainSecurityGroup.DEV
  • MyDomainSecurityGroup.TST
  • MyDomainSecurityGroup.PRD

Then update the local security groups on your servers to ONLY contain one of these domain security groups. If the server is a DEV server, put the DEV make the DEV domain group the only member of the local security group. All other user/service accounts should be removed from the local security group and added to the appropriate domain security group.

Conclusion

If you follow this pattern to secure your web services, you’ll be able to prevent unauthorized access to your service by adding a single line of code to every method that needs to check authorization. Furthermore, in a more complex scenario – say one where users may have read, write or admin access to your service – you can create as many local and domain security groups as you need to ensure that users and applications have the lowest level of access required to do their work.

One final thought: If you web service is hosted in across a pool of servers, remember to create the local security groups on all of the servers. You could probably do this with your installer. Or, you could make it a manual step in your implementation plan that only gets executed once.

.NET Reflector: Your personal X-Ray machine

Have you ever run across a situation where you were trying to debug some code, but you hit a wall when you ran into an object that you don’t own? Happens to me more often than I like. And, before I learned about .NET Reflector, I was stuck using debug.print statements on either side of the object call to figure out what was going on inside.

.NET Reflector changes all that. Need to see the code for an object you don’t own? Crack open any .NET assembly with reflector.exe and disassemble the code. Here the disassembly of a method from a WCF service I wrote recently:

image

You can even use this tool to disassemble objects in the .NET Framework!

Plus, .NET Reflector includes a Visual Studio add-in that lets you debug into this disassembled code! So, no more debug.print. Just follow the flow of execution right on into that code you don’t own. Who knows, you may even find someone else’s bug in the process of solving your own!

Coding Standards

One of the original practices of Extreme Programming was coding standards. Back in 2000, when I read my first XP book, I tensed up a bit at the thought of having to make my code look like everyone else’s. But, over the years, I’ve come to see the wisdom of it: once all the code follows the same standard, it becomes much easier to read.

In fact, now a days, I often reformat a block of code to meet a coding standard before I try to figure out what it’s doing. (But, only when I have strong unit tests!) Long story short, I haven’t had a good knock-down-drag-out argument about curly braces in nearly ten years! (Anyone want to have one for old time’s sake?)

With that in mind, I needed to look up Microsoft’s latest guidelines for .NET class libraries, today. Specifically, I knew they said something about using abbreviations and acronyms when naming things. But, I couldn’t remember exactly what the recommendation was. So, I looked it up. Turns out, Microsoft has done a rather nice job of structuring their design guidance on the web.

It’s not something you’ll need to refer to everyday. But, it’s good to know it’s out there…

http://msdn.microsoft.com/en-us/library/czefa0ke(v=VS.71).aspx