Authentication is the process of identifying the user, and authorization occurs afterward to verify if the identified user is allowed to access a specific resource.
Identity and Principal
You can identify the user running the application by using an identity. The Windows Identity class represents a Windows user. If you don’t identify the user with a Windows account, you can
use other classes that implement the interface IIdenti ty. With this interface you have access to the name of the user, information about whether the user is authenticated, and the authentication type. principal is an object that contains the identity of the user and the roles that the user belongs to. The interface IPrincipal defines the property Identi ty that returns an IIdenti ty object and the method IsInRole in which you can verify if the user is a member of a specific role. A role is a collection of users who have the same security permissions, and it is the unit of dministration for users. Roles can be Windows groups or just a collection of strings that you define.
Principal classes available with .NET are Windows Principal and GenericPrincipal. You can also create a custom principal class that implements the interface IPrincipal. In the following example, you create a console application that provides access to the principal in an application that, in turn, enables you to access the underlying Windows account. You need to import the Sys tern. Secur i ty . Pr inc ipal and Sys tern. Threading namespaces. First of all, you must specify that .NET automatically hooks up the principal with the underlying Windows account. This is because .NET does not automatically populate the thread’s CurrentPrincipal property for security reasons. You can do it like this:
using System. Threading
It is possible to’~se Windowsldenti ty. GetCurrent () to access the Wmdows account details; however, that method is best used when you are going to look at the principal only once. If you want to access the principal a number of times, it is more efficient to set the policy so that the current thread provides access to the principal for you. If you use the Set Principal Policy method, it is specified that the principal in the current thread should hold a windowsldenti ty object. All identity classes, such as \\’indowsldenti ty, implement tht?”Irdenti ty interface. The interface contains three properties (Aut hen t i ca t Lon’rype, IsAuthenticated, and Name) for all derived identity classes to implement.Add code to access the principal’s properties from the Thread object:
The output from this console application looks similar to the following lines; it wi~ vary according to your machine’s configuration and the roles associated with the account under which you are signed in: IdentityType:System.Security.Principal.Windowsldentity
It is enormously beneficial to be able to easily access details about the current users and their roles. With this information, you can make decisions about what actions should be permitted or denied. The ability to make use of roles and Windows user groups provides the added benefit that administration can be done by using standard user administration tools, and you can usually avoid altering the code when user roles change. The following section looks at roles in more detail.
Role-based security is especially useful in situations in which access to resources is an issue. A primary example is the finance industry, in which employees’ roles define what information they can access and what actions they can perform.
Role-based security is also ideal for use in conjunction with Windows accounts, or a custom user directory to manage access to Web-based resources. For example, a Web site could restrict access to its content until a user registers with the site, and then additionally provide access to special content only, if the user is a paying subscriber. In many ways, ASP.NET makes role-based security easier because much of the code is based on the server
For example, tq’)mplement a Web service that requires authentication, you could use the account subsystem of Windows and write the Web method in such a way that it ensures the user is a member of a specific Windows user group before allowing access to the method’s functionality.
Imagine a scenario with an intra net application that relies on Windows accounts. The system has a group called Manager and one called Assistant; users are assigned to these groups according to their role within the organization. Say that the application contains a feature that displays mformation about : employees that should be accessed only by users in the Managers group. You can easily use code that checks whether the current user is a member of the Managers group and whether he is permitted or denied access.
However, if you dec”ide later to rearrange the account groups and to introduce a group called Personnel that also has access to employee details, you will have a problem. You will need to go through all the code and update it to include rules for this new group.
A better solution would be to create a permission c~lled something like ReadEmployeeDetails and assign it to groups where necessary. If the code applies a check for the ReadEmployeeDetails permission, updating the application to allow those in the Personnel group access to employee details is simply a matter of creating the group, placing the users in it, and assigning the ReadEmployeeDetails permission.
Declarative Role-Based Security
Just as with code access security, you can implement role-based security requests (“the user must be ill the Administrators group”) using imperative requests by calling the IsInRole () method from the
IPrincipal class, or using attributes. You can state permission requirements declaratively at the class or method level using the [PrincipalPermission] attribute:
using System. Security;
The ShowMessage () method will throw an exception unless you execute the application in the context of a user in the Windows local Users group. For a Web application, the account under which the ASP.NETcode is running must be in the group, although in a “real-world” example you would certainly avoid adding this account to the administrators group! If you run the preceding code using an account in the local Users group, the output will look like this: The current principal is logged in locally (member of the local Users group)
Client Application Services
Visual Studio 2008 makes it easy to use authentication services that previously have been built for ASP.NET Web applications. With this service, it is possible to use the same authentication mechanism both with Windows and Web applications. This is a provider model that is primarily based on the classes Membership and Roles in the namespace System. Web. Security. With the Membership
class you can validate, create, delete, find users, change the password, and other various things related to users. With the Roles class you can add and delete roles, get the roles for a user, and change roles from a user. Where the roles and users are stored depends on the provider. The Acti veDirectoryMembershipProvider accesses users and roles in the Active Directory; the SqlMembershipProvider uses a SQL Server database. For client application services new providers exist with .NET 3.5: ClientFormsAuthenticatiOnMembershipProvider and ClientWindowsAuthertticationMembershipProvider
Next, you use client application services with Forms authentication. To do this, first you need to start an application server, and then you can use this service from Windows Forms or WPF.
For using client application services, you can create an ASP.NET Web service project that offers application services. . With the project a membership provider is needed. The sample code here defines the class SampleMembershipProvider that derives from the base class MembershipProvider. You must override all abstract methods from the base class. For login, the only implementation needed is the method validateUser. All other methods can throw a NotSupportedException as shown with the property ApplicationName. The sample code here uses a Dictionary<string, string> that contains usemames and passwords. Of course, you can change it to your own implementation, for example, to read usemame and password from the database
using System. web. Security;
For using roles,you alsoneed to implement a roleprovider.The classSarnpleRoleProvider derives from the base classRoleProvider and implements the methods GetRolesForUser () and IsUserlnRole (r
using System. web. Security;
Authentication servicesmust be configured in the Web. config file.On the production system, itwould be useful from a securitystandpoint to configure SSL with the server hosting application services
Within the <system. web> section,the membership and roleManager elements must be configured to reference the classesthatimplement the membership and role provider:
For debugging, you can assign a port number and virtual path with the Web tab of project properties. The sample application uses the port 55555 and the virtual path 1AppServices. If you use different values, you need to change the configuration of the client application accordingly. Now the application service can be used from a client application.
With the client application WPF is used. Windows Forms can be used in the same way. Visual Studio 2008 has a new project setting named Services that allows using client application services. Here you can set Forms authentication and the location of the authentication and roles service to the address defined previously: http://localhost : 555551 AppServices. All that’s done from this project configuration s referencing the assemblies System. web and System. Web.Extensions, and changing the application configuration file to configure membership and role providers that use the classes ClientFormsAuthenticationMembershipProvider and ClientRoleProvider and the address of the Web service that is used by these providers.
The Windows application just uses Label, TextBox, PasswordBox, and Button controls as shown in Figure 20-1. The Label with the content User Validated shows up only when the logon is successful.
‘the handler of the Button. Click event invokes the ValidateUser () method of the Membership class. Because of the configured provider ClientAuthenticationMembershipProvider, the provider in turn invokes the Web service and calls the method validateUser () of the SampleMembershipProvider class to verify a successful logon. With success, the Label labelValidatedlnfo is made visible; otherwise a message box pops up: