MSDN Magazine - October 2008 - (Page 65) DOmInICk BAIer AnD ChrIStIAn Weyer Service Station Authorization In WCF-Based Services Once you start adopting service-oriented principles for your distributed applications, the security challenges become slightly different. You suddenly realize that you are crossing a security boundary for every service call you make. Typically—though not necessarily—there will be a network between the sender and the recipient of a service call. While authentication is usually handled automatically by the communication framework, you still have to come up with your own authorization strategy and infrastructure. Windows Communication Foundation (WCF) provides powerful facilities for implementing authorization in services. You have the choice between an easy-to-use, role-based system as well as a more powerful, but more complex, claims-based API. The remainder of this article will compare both systems and show how to use them to implement robust service authorization. Figure 1 Role Check with Error Handling Service class Service : IService { // only 'users' role member can call this method [PrincipalPermission(SecurityAction.Demand, Role = 'users')] public string[] GetRoles(string username) { // only administrators can retrieve the role information for other users if (ServiceSecurityContext.Current.PrimaryIdentity.Name != username) { if (Thread.CurrentPrincipal.IsInRole('administrators')) { } else { // access denied throw new SecurityException(); } } } } Client var factory = new ChannelFactory ('*'); factory.Credentials.UserName.UserName = 'bob'; factory.Credentials.UserName.Password = 'bob'; var proxy = factory.CreateChannel(); try { Console.WriteLine('\nBob: roles for Bob --'); proxy.GetRoles('bob').ToList().ForEach(i => Console.WriteLine(i)); Console.WriteLine('\nBob: roles for Alice --'); proxy.GetRoles('alice').ToList().ForEach(i => Console.WriteLine(i)); Role-Based Authorization The idea behind role-based authorization is that you associate a list of roles with a user. At run time, the service code queries the list to make security-related decisions. These roles can come from the Windows security system (where they are called groups) or from some custom store, such as a database. The roles API in the Microsoft .NET Framework is based on two interfaces called IIdentity (identity information) and IPrincipal (role information). An IIdentity-derived class holds information such as the name of the user, whether he is authenticated, and how he was authenticated. An IPrincipal-derived class must implement a single method called IsInRole where you can pass in a role name and get a Boolean response. In addition, the principal has a reference to the identity class it wraps. The .NET Framework ships with several implementations of theses interfaces. WindowsIdentity and WindowsPrincipal wrap details about a Windows user. GenericIdentity and GenericPrincipal can be used to represent a custom, authenticated user. There is also a location where you can store a principal to associate it with the currently executing thread in your application (for example, a WCF operation request). This is the CurrentPrincipal thread static property on the System.Threading.Thread class. The typical course of events is that one part of an application populates Thread.CurrentPrincipal so that another part of the application can reach into this property to grab the IPrincipal implementation } catch (SecurityAccessDeniedException) { Console.WriteLine('Access Denied\n'); } stored there. Then the IsInRole method can be called on that class to query the role list of the current user to ensure that the caller is authorized for the operation. This is exactly how it works in WCF. Based on the configured authentication and credential type, WCF creates a corresponding IIdentity implementation—a WindowsIdentity for Windows authentication, a GenericIdentity for most other cases. Then, based on the configuration of the WCF service behavior, ServiceAuthorization, an IPrincipal implementation is created that wraps this identity and provides role information. This IPrincipal is then set on Thread.CurrentPrincipal so that it is accessible to the service operations. Send your questions and comments to sstation@microsoft.com. Code download available at msdn.microsoft.com/magazine/cc135911. October 2008 65 http://msdn.microsoft.com/magazine/cc135911
For optimal viewing of this digital publication, please enable JavaScript and then refresh the page. If you would like to try to load the digital publication without using Flash Player detection, please click here.