Top Banner
Security Features in ASP.NET - Authentication Introduction Security is one of the primary concerns for both developers and application architects. As there are lots of different types of website with varying security needs, the developers need to know how the security works and choose the appropriate security model for different applications. Some websites collect no information from the users and publish the information that is available widely such as search engine. Meanwhile, there are other sites that may need to collect sensitive information from their users (e.g. credit card numbers and other personal information). These websites need much stronger security implementation to avoid malicious attacks from external entities. Difference of ASP and ASP.NET Security Flow The security flow for ASP.NET page request is different from the classic ASP security flow. In ASP, IIS impersonates the authenticated user by default, and in ASP.NET, the developer has more control over configuring security at different level [2] . ASP.NET Security Fundamental Operations Security in the context of ASP.NET application involves 3 fundamental operations [1,4,5] : Authentication: the process of validating the identity of a user to allow or deny a request [4,9,10] . This involves accepting credentials (e.g. username and password) from the users and validating it against a designated authority. After the identity is verified and validated, the user is considered to be legal and the resource request is fulfilled. Future request from the same user ideally are not subject to the authentication process until the user logs out of the web application. Authorization: the process of ensuring that users with valid identity are allowed to access specific resources. Impersonation: this process enables an application to ensure the identity of the user, and in turn make request to the other resources. Access to resources will be granted or
63
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Security Features in ASP

Security Features in ASP.NET - Authentication

Introduction

Security is one of the primary concerns for both developers and application architects. As there are lots of different types of website with varying security needs, the developers need to know how the security works and choose the appropriate security model for different applications. Some websites collect no information from the users and publish the information that is available widely such as search engine. Meanwhile, there are other sites that may need to collect sensitive information from their users (e.g. credit card numbers and other personal information). These websites need much stronger security implementation to avoid malicious attacks from external entities.

Difference of ASP and ASP.NET Security Flow

The security flow for ASP.NET page request is different from the classic ASP security flow. In ASP, IIS impersonates the authenticated user by default, and in ASP.NET, the developer has more control over configuring security at different level [2].

ASP.NET Security Fundamental Operations

Security in the context of ASP.NET application involves 3 fundamental operations [1,4,5]:

Authentication: the process of validating the identity of a user to allow or deny a request [4,9,10]. This involves accepting credentials (e.g. username and password) from the users and validating it against a designated authority. After the identity is verified and validated, the user is considered to be legal and the resource request is fulfilled. Future request from the same user ideally are not subject to the authentication process until the user logs out of the web application.

Authorization: the process of ensuring that users with valid identity are allowed to access specific resources.

Impersonation: this process enables an application to ensure the identity of the user, and in turn make request to the other resources. Access to resources will be granted or denied based on the identity that is being impersonated. In other words, impersonation enables a server process to run using the security credentials of the client [6,9]. Thus, the ASP.NET applications are capable to execute the identity of client on whose behalf they are operating.

Since there are a lot of ASP.NET security features to cover, this paper will only focus on authentication in ASP.NET.

Authentication in ASP.NET

Authentication is one of the foremost features of web application's security. In ASP.NET, authentication is done at two levels [2]. First, IIS* will perform the required authentication then send out the request to ASP.NET, as described in Figure 1. For ASP.NET application, the

Page 2: Security Features in ASP

underlying web server is IIS. Therefore, every ASP.NET application can continue to leverage the security options provided by IIS.

Page 3: Security Features in ASP

Source: MSDN LibraryFigure 1 - Security Flow of IIS and ASP.NET

When the user requests a specific resource on the system, that request will come to IIS. IIS authenticates the user requesting the resource and then hands off the request and the security token for the authenticating user to ASP.NET worker process. ASP.NET worker process will decide whether to impersonate the authenticated user supplied by IIS or not.

If impersonation is enabled in the configuration setting in Web.config file, then ASP.NET worker process impersonates the authenticated user. Otherwise, the thread will run under the ASP.NET worker process identity. After all, ASP.NET checks whether the authenticated user is authorized to access these resources. If they are allowed to, ASP.NET serves the request; otherwise it sends an "access-denied" error message back to the user.

ASP.NET provides built-in support for user authentication through several authentication providers [1,4]:

Forms-based authentication: the application is secured by using a custom authentication model with cookie support.

Passport authentication: the application is secured by using Microsoft® Passport authentication. Passport is a single sign-on technology developed by Microsoft for use on the web.

Windows authentication: the application is secured by using integrated windows authentication where access to a web application is allowed only to those users who are able to verify their windows credentials.

There are scenarios where some applications do not use the authentication at all or the developer may want to develop custom authentication code. In this case, ASP.NET can set the authentication mode to None. However, the topic is out of scope of this article since it will only cover the Forms-based, passport and windows authentications.

Forms-Based Authentication

Forms-based authentication is used to implement customized logic for authenticating users without having to worry about session management using cookie. It gives developer more access to specify which files on the site can be accessed and by whom, and allows identification of a login page [3,7].

This mechanism will automatically redirect the unauthenticated user to login page and ask them to provide proper credentials (e.g. username/password combination). If login is successful, ASP.NET then issues the cookie to the user and redirect them to specific resources that they originally requested. This cookie allows the user to revisit particular protected resources without having to repeatedly log in. The mechanism is shown as below:

Page 4: Security Features in ASP

Figure 2 - Form Authentication Flow

In figure above, the user requests the restricted resources first. This request will go to IIS first and the user is authenticated by IIS. If the anonymous access is enabled in IIS or the user is successfully authenticated, it will hand off the request to ASP.NET application. ASP.NET checks to see whether a valid authentication cookie is attached to the request. If it is, it means the user credentials has been previously authenticated. ASP.NET will then perform the authorization check. If the user is authorized to access those resources, the access will be granted. Otherwise, the "access-denied" message is sent.

If the request does not have any cookie attached, ASP.NET redirects the user to the login page and solicits the credentials then resubmits for authentication. The application code checks those credentials. If authenticated, ASP.NET will attach the authentication ticket in the form of cookie to the response. If failed, the user can be redirected back to the login page telling the user that the username/password is invalid.

Set Up Forms-Based Authentication

Generally, setting up the Forms-based authentication involves 4 steps [2]:

1. Enable anonymous access in IIS

Page 5: Security Features in ASP

This has to be done as most of the users are considered to be non-Windows users, so they can get through IIS to get to ASP.NET. ASP.NET will always allow anonymous access to the login page though.

2. Configure <authentication> section in Web.config file

Web.config file contains the information related to the level and type of authentication service that is provided for a web application. The Forms-based authentication is enabled for a web application by setting the authentication mode attribute to Forms [3,8]:

<authentication mode="Forms"> <forms name="Login" loginURL="Login.aspx" protection="All" timeout="10" path="/" /></authentication>

As shown by the code above, the name attribute is the name of HTTP cookie. The attribute loginURL is set to Login.aspx, which is the web page that is used for authenticating user credentials. The requests are redirected to particular URL in loginURL if the user is not authenticated.

The cookie protection is set to All. This causes the ASP.NET runtime to not only encrypt the cookie contents, but also validate the cookie contents. The valid values for protection attribute are All, None, Encryption, and Validation [9,10]. If the value is specified to None, it does not use either encryption or validation. Specifying Encryption will encrypt the cookie using triple DES or DES encryption algorithm; the data validation is not done on the cookie. The Validation specifies to validate that the cookie data has not been altered in the transit, instead of encrypting the contents of the cookie.

The timeout is set to 10, which means in 10 minutes the authentication cookie will expire. The idea behind this is to reduce the chance someone stealing the form authentication cookie. By reducing this, the cookie will be regenerated more often.

The path attribute refers to the path of cookie to be sent to the client. It is set to "/" which means the cookie path is the root directory.

The actual authentication (i.e. prompting the user to provide credentials) is performed by Login.aspx. The following code in Login.aspx passes the username and password that the user entered to the static System.Web.Security.FormsAuthentication method called Authenticate:

If(FormsAuthentication.Authenticate(Username. Text, Password. Text)){

Page 6: Security Features in ASP

FormsAuthentication.RedirectFromLoginPage (Username. Text, false);}

The code above will first check the username and password passed by the user, if they are valid, it will return true then go to the next statement. Next, it creates an authentication cookie, attaches it to the outgoing response and redirects user to original requested page. The second parameter specifies whether the authentication should be session cookie (false) or a persistent cookie (true) [7].

3. Configure <authorization> section in Web.config file

Add authorization support to section of ASP.NET web application. To do so, add the <authorization> section in Web.config file:

<configuration> <system.web> <authorization> <allow users="Cynthia" /> <deny users="*" /> </authorization> </system.web></configuration>

As explained above, after the user provides the valid credentials, the user is redirected to the specific protected page. However, The authorization section in this code will deny access to all users, but exclusively allow access to Cynthia.

In some cases, the following code is used to allow any authenticated user to access the protected resources [2]:

<authorization> <deny users="?" /> <allow users="*" /></authorization>

The "?" means all unauthenticated, anonymous user [5]. It will deny all unauthenticated or anonymous users.

One important thing to note that the code:

<deny users="*" /><allow users="Cynthia" />

Page 7: Security Features in ASP

is different from:

<allow users="Cynthia" /><deny users="*" />

since ASP.NET will stop at <deny users="*" /> and abandon the rest statements appear after that [7]. Therefore in the first one, it will deny ALL users instead of giving access to Cynthia only.

4. Create Login Page

This is the last step for redirecting unauthenticated users, so they can provider their credentials, usually in a form of username and password and log on to protected resources. The login page must validate the submitted credentials against a database of some custom method. Valid usernames and passwords can be stored in the Web.config file in credentials section:

<credentials passwordFormat="Clear"> <user name="Cynthia" password="cyn"> <user name="Flora" password="flo"> <user name="Fenty" password="fang"></credentials>

However, storing password in clear text is unreasonable for security. Moreover, it is unrealistic to store thousands of names and passwords in Web.config file [2,7]. To address this problem, the usernames and passwords are stored in the database. This approach makes the Web.config file no longer have the <credentials> section. There will be also some changes in Login.aspx since the credentials will be tested to match against result query from database that stores the usernames and passwords.

In Login.aspx, instead of using FormsAuthentication.Authenticate to validate user credentials, it will call a local method (i.e. CheckValidity) which makes use a SQL query to determine whether the credentials are valid. The sample code as follows:

Bool CheckValidity(String username, String password){ SqlConnection conn = new SqlConnection ("server=localhost; database=weblogin; uid=sa; pwd="); try { conn.Open(); String sqlQuery = "select count (*) from users where username =\' " + username + "\' and password=\' " + password + "\' "; SqlCommand command = new SqlCommand(sqlQuery, conn);

Page 8: Security Features in ASP

int count = (int)command.ExecuteScalar(); return (count>0); }

catch (SqlException e) { return false; } finally { conn.Close(); }}

This function will check for username and password given by the user to match against the database (i.e. users table) and it will return 0 if the credentials are not valid because there is no such record in the database, otherwise it will return 1, which means the credentials are valid.

Benefit of Forms-Based Authentication

There are some benefits of using Forms-based authentication [5]:

Developer can configure Forms-based authentication for various parts of the website differently because the Web.config is a hierarchical XML document.

Administrator and developer can change the authentication scheme quickly and easily in the Web.config file

Administration is centralized because all the authentication entries are in one place - Web.config file.

Passport Authentication

As stated above, this authentication mechanism provides a centralized authentication service that offers single sign-in for access the member sites. The following scenarios support the use of Passport Authentication [2]:

The username and password database or login page is not maintained; and Willing to provide personalized content; and The site will be used in conjunction with other Passport sites; and Willing to give single sign-in capability to the users

Set Up Passport Authentication

To implement this authentication mode, Passport SDK (Software Development Kit) has to be installed on the server and register with Microsoft® Passport [1,2]. The following code is specified in the Web.config file where the authentication mode is set to Passport:

Page 9: Security Features in ASP

<authentication mode="Passport"> <passport redirectURL="internal" /></authentication>

The redirectURL attribute of Passport section is set to internal, which means the unauthenticated request will receive common error message. The value of redirectURL may contain a string other than internal, which is considered to be a URL, which the unauthenticated request will be sent to.

Windows Authentication

This type of authentication is possibly the easiest of all to implement. Windows authentication can be used in conjunction with almost all authentication methods provided by IIS (e.g. Basic, Digest, NTLM or Kerberos Authentication), except Anonymous Authentication [2,4]. There is no need to write any code to validate the user as IIS has already authenticated their Windows credentials. Basically, Windows authentication makes use of the authentication capabilities of IIS. IIS will complete its authentication first then ASP.NET will use the authenticated identity's token to decide whether the access is granted or denied.

This mechanism is usually implemented when the users are part of Windows domain and the authenticated users are to be impersonated so that the code is executed in the same security context of the user's Windows account [4].

When a user requests specific resources, this request will go to IIS. IIS authenticates the user and attaches the security token to it. It will then pass the authenticated request and security token to ASP.NET. If impersonation is enabled, ASP.NET impersonates the user using the security token attached and sees whether the user is authorized to access the resources in the <authorization> section in Web.config file. If the access is granted, ASP.NET will send the requested resources through IIS, or else, it sends error message to the user.

Set Up Windows Authentication

The only step in implementing the Windows Authentication is to set the authentication mode to Windows and deny access to anonymous user in Web.config file as shown below:

<authentication mode="Windows"> ...</authentication>

<authorization> <deny users="?" /></authorization>

Page 10: Security Features in ASP

The impersonation is enabled only if the code is to be under same security context as that of the user account. Again, this is done in the configuration file.

Conclusion

Authentication in ASP.NET is one of the best features of the web application's security, which it is divided into 3 different built-in providers: Forms-based, Passport and Windows Authentication. The Forms-based and passport authentication do not require the users to be as Windows users. Meanwhile, the windows authentication is designed for users that are part of Windows domain. Forms-based authentication provides the unauthenticated users with the login page to ask them for their credentials, and it will validate those credentials against the designated authority. Once authenticated, the valid users will be granted to access the original requested resources. Future request from those users of the protected resources will automatically be redirected without having to repeatedly log in. On the other hand, if the users are not authorized to access specific resources, it will send the access-denied message back to the users. For Passport authentication, just simply install the Passport SDK on the server and register with Microsoftâ Passport. This mechanism offers a single sign-in provided by Microsoft to allow access to the member sites. Whereas, the Windows authentication is the easiest to implement as it does not require writing any code for authentication. It works in conjunction with IIS authentication mechanisms such as Basic, Digest, NTLM or Kerberos. However, it does not support for IIS Anonymous authentication.

ASP.NET Security [Part I]

Security is one of the most important concerns in application software development. Building a

robust security model is one of the most important factors that drive the success of application

software. As far as security in ASP.NET is concerned, three terms come into my mind, i.e.,

Authentication, Authorization and Impersonation. Put simply, authentication authenticates the

user’s credentials and authorization relates to the resources that an authenticated user has

access to. This article is the first in a series of articles on ASP.NET security and discusses these

concepts and their applicability.

Let us start our discussion with a brief outline on the sequence of events are as far as

authentication and authorization are concerned when a new request comes in. When a new

request arrives at IIS, it first checks the validity of the incoming request. If the authentication

mode is anonymous (default) then the request is authenticated automatically. But if the

authentication mode is overridden in the web.config file settings, IIS performs the specified

authentication check before the request is passed on to ASP.NET.

ASP.NET then checks whether Impersonation is enabled or not. We will discuss impersonation

Page 11: Security Features in ASP

later in this article. If impersonation is enabled, ASP.NET executes with the identity of the entity

on behalf of which it is performing the task; otherwise, the application executes with the

identity of the IIS local machine and the privileges of the ASP.NET user account. Finally, the

ASP.NET engine performs an authorization check on the resources requested by the

authenticated user and if the user is authorized, it returns the request through IIS pipeline.

The following section discusses Authentication, Authorization and Impersonation and how we

can implement them in ASP.NET applications.

Authentication

Authentication determines whether a user is valid or not based on the user’s credentials. Note

that a user can be authorized to access the resources provided the user is an authenticated user.

The application’s web.config file contains all of the configuration settings for an ASP.NET

application. An authentication provider is used to prove the identity of the users in a system.

There are three ways to authenticate a user in ASP.NET:

Forms authentication

Windows authentication

Passport authentication

Forms Authentication

This is based on cookies where the user name and the password are stored either in a text file or

a database. It supports both session and persistent cookies. After a user is authenticated, the

user’s credentials are stored in a cookie for use in that session. When the user has not logged in

and requests for a page that is secured, he or she is redirected to the login page of the

application. The following code snippet illustrates how this can be implemented in ASP.NET.

<configuration>

<system.web>

Page 12: Security Features in ASP

<authentication mode="Forms"/>

<forms name="LoginForm" loginUrl="LoginForm.aspx" />

<authorization>

<deny users="?"/>

</authorization>

</system.web>

</configuration>

Note that the symbol "?" indicates all Non Authenticated and Anonymous users. Typically, the

user enters the username and the password, clicks the login button and the form validates the

values against values from that stored in a persistent store, usually a database. The following

code snippet illustrates how this can be validated.

String username = txtUserName.Text;

String password = txtPassword.Text;

bool isUserValid = false;

//Code to validate the user name and password

if(isUserValid)

{

FormsAuthentication.RedirectFromLoginPage(txtUserName.Text, False);

else // User is not valid

lblMessage.Text = “Invalid login…”;

}

The RedirectFromLoginPage method creates an authentication ticket and is used to redirect an

authenticated user back to the originally requested URL or the default URL. The following code

snippet illustrates how we can specify the user’s credentials in the application’s web.config file.

<configuration>

<system.web>

<authentication mode="Forms">

<forms loginUrl="LoginForm.aspx">

Page 13: Security Features in ASP

<credentialspasswordFormat="Clear">

<user name="JoydipK" password="JudeK" />

</credentials>

</forms>

</authentication>

<authorization>

</system.web>

</configuration>

However you choose the above technique of authentication you should provide a means of

encrypting the configuration file for security reasons. I will discuss these and other issues in the

forthcoming articles in this series of articles on ASP.NET Security.

You can also use Forms Authentication to verify the user’s credentials using a database where

the user’s credentials are stored. The following code example illustrates how this can be

achieved. The method ValidateUserCredentials accepts a user name and the password, connects

to the database where the user’s credentials is stored and verifies whether the supplied user’s

credentials are correct.

private bool ValidateUserCredentials(String userName, String password)

{

// Connect to the database where the user credentials are stored and then verify whether the

user's credentials that

// are passed as parameters to this method are correct. The method would return true if

success, false otherwise.

}

The above method can be called as illustrated in the code snippet below.

bool isAuthenticatedUser = false;

try

{

isAuthenticatedUser = ValidateUserCredentials(txtUserName.Text,txtPassword.Text);

}

Page 14: Security Features in ASP

catch(Exception ex)

{

//Some typical exception handling code

}

if (isAuthenticatedUser == true )

{

//The user is authenticated, hence, redirect to the appropriate web form and/or display

appropriate messages to the user

}

else

{

//Display appropriate messages to the user indicating that the user is not authenticated

}

Windows Authentication

Windows Authentication is used to validate a user based on the user’s Windows Account;

however, this is only applicable in intranet environments where the administrator has full

control over the users in the network. The following code snippet illustrates how we can

implement Windows Authentication in ASP.NET.

<authentication mode="Windows"/>

<authorization>

<allow users ="*" />

</authorization>

Note that the symbol "*" indicates all users inclusive of Authenticated and Anonymous users.

Windows authentication can be of the following types

Anonymous Authentication

Basic Authentication

Digest Authentication

Integrated Windows Authentication

Page 15: Security Features in ASP

In the Anonymous Authentication mode IIS allows any user to access an ASP.NET application

without any authentication checking.

In Basic Authentication mode users will be required to provide the Windows user name and

password; however, this is very insecure.

The Digest Authentication mode is identical to Basic Authentication with the exception that the

password is hashed before it is sent across the network.

In Integrated Windows Authentication mode, the passwords are not sent across the network;

rather, the application uses some network authentication protocols for it to operate.

Passport Authentication

Passport authentication is a centralized authentication service that uses Microsoft's Passport

Service to authenticate the users of an application. It allows the users to create a single sign-in

name and password to access any site that has implemented the Passport single sign-in (SSI)

service. The following code snippet illustrates how we can implement Passport Authentication in

ASP.NET.

<configuration>

<system.web>

<authenticationmode="Passport">

<passportredirectUrl="LoginForm.aspx" />

</authentication>

<authorization>

<deny users="?" />

</authorization>

</system.web>

</configuration>

Authorization

Authorization is the process of determining the accessibility to a resource for a previously

authenticated user. Note that authorization can only work on authenticated users, hence

Page 16: Security Features in ASP

ensuring that no un-authenticated user can access the application. The syntax for specifying

authorization in ASP.NET is as follows.

<authorization>

< [ allow | deny ] [ users ] [ roles ] [ verbs ] />

</authorization>

In ASP.NET, there are the following types of authorizations.

URL Authorization

File Authorization

Authorization based on ACLs

File Authorization is performed by the FileAuthorizationModule, and is active when the

application is configured to use Windows authentication. It checks the access control list ( ACL )

of the file to determine whether a user should have access to the file. ACL permissions are

verified for the Windows identity or, if impersonation is enabled, for the Windows identity of

the ASP.NET process.

URL authorization is performed by the URLAuthorizationModule, which maps users and roles to

URLs in ASP.NET applications. This module can be used to selectively allow or deny access to

arbitrary parts of an application ( typically directories ) for specific users or roles.”

Authorization like authentication is specified in the web.config file of the application. The

following is an example of how we can use authorization in ASP.NET using the application’s

configuration file.

<authorization>

<allow users="Joydip"/>

<deny users="Jude"/>

<deny users="?"/>

</authorization>

Page 17: Security Features in ASP

It is also possible to specify the location to which the authorization settings defined in that

particular location is applicable. Refer to the following code snippet that illustrates this.

<configuration>

<location path = "Test.aspx">

<system.web>

<authorization>

<allow users = "?" />

</authorization>

</system.web>

</location>

</configuration>

You can also restrict or grant a GET or POST to one or more users of the ASP.NET application.

The following code snippet illustrates how we can allow the user “Jude” to do a POST while the

other users can do only a GET.

<authorization>

<allow verb = "GET" users = "*" />

<allow verb = "POST" users = "Jude" />

<deny verb = "POST" users = "*" />

</authorization>

Impersonation

According to MSDN, "When using impersonation, ASP.NET applications can optionally execute

with the identity of the client on whose behalf they are operating. The usual reason for doing

this is to avoid dealing with authentication and authorization issues in the ASP.NET application

code. Instead, you rely on Microsoft Internet Information Services (IIS) to authenticate the user

and either pass an authenticated token to the ASP.NET application or, if unable to authenticate

the user, pass an unauthenticated token. In either case, the ASP.NET application impersonates

whichever token is received if impersonation is enabled. The ASP.NET application, now

impersonating the client, then relies on the settings in the NTFS directories and files to allow it

to gain access, or not. Be sure to format the server file space as NTFS, so that access permissions

can be set”.

Page 18: Security Features in ASP

Note that Impersonation is disabled by default and can be specified in the web.config file as

shown in the code snippet given below.

<identity impersonate="true"/>

or

<identity impersonate="false"/>

To impersonate a particular identity, specify the following in your application’s web.config file.

<identity impersonate="true" username="joydip" password="jude"/>

Conclusion

We have had a look at some of the most important concepts related to ASP.NET security. Stay

tuned for the other articles in this series that will discuss other aspects of ASP.NET security.

Implementing Role-Based Security with ASP.NET

Before we start, let's take a quick look at what roles are, and how they might be commonly used within an application. Imagine for a moment that you have been assigned the task of converting an online forum from Classic ASP to ASP.NET. One of the hurdles that you are likely to face lies in determining the identities of the users, and then granting access to certain features based on who that user is and what "role" they play within the application.

As you begin to form a picture of what roles are required, you might find that you end up with four basic "classes" of user:

1. System Administrator - this class of user can perform any task - add/delete posts and forums, ban users, approved messages posted to moderated forums, etc.

2. Moderator - this user can only approve messages that were posted to moderated forums.

Page 19: Security Features in ASP

3. Subscriber - these are users that are registered and authorized to post new messages, but are restricted from all administrative areas of the site.

4. Other/Public - these users merely have permission to browse to public pages within the site and read-only access to forum posts.

If you've come straight out of developing classic ASP applications, your first instinct may be to maintain user state in the Session object, and, then do some type of database lookup for an associated UserType to establish the role of the user. (In fact a previous 4Guys article, Logins and Permissions, demonstrates how to accomplish this "role"-based authorization using Session variables in classic ASP.)

Dim currentUserID, userType

currentUserID = Session("UserID")userType = myDatabaseLookupFunction( currentUserID )

' Only allow System Administrators and ModeratorsSelect Case userType

Case "1", "2" :' User is OK

Case Else :' Redirect to unauthorized access page

End Select

Typically, classic ASP applications relied heavily on this type of model, involving repeated database lookups to retrieve role based information.

With ASP.NET, however, this model changes. Before examining how roles are handled in ASP.NET, let's first translate the classic ASP Session-based code from above into VB.NET code that would appear in our ASP.NET Web page:

If User.IsInRole("SysAdmin") OrElse User.IsInRole("Moderator") Then' User is OK

Else' Redirect to unauthorized access page

End If

Although the above code probably doesn't mean much to you yet, it will by the time we've finished. Essentially, you can see that we interrogate a User object to extract the role information. But what is this User object?, And how does it get the role information?, I hear you asking.

Principals, Roles, and Identities, Oh My!If you've done any administering of Windows you will be familiar with the concept of Users and Groups. Basically, to access a secured network you must have a user account and that account would be assigned to one or many groups. In .NET these are referred to as Identities and Roles respectively, and they are contained within a Principal object. To understand how role based

Page 20: Security Features in ASP

authorization works you need to have an understanding of how these three elements are tied together, and how you can programmatically access their values. Let's look at each element separately.

IdentitiesIdentities represent users, and as such, have properties that allow you to obtain information (such as the username) about that user.

The classes for working with Identities reside in the System.Security.Principal Namespace. This namespace contains two classes: GenericIdentity and WindowsIdentity through which you can determine the properties of a user; and one interface: IIdentity that you can use to create custom Identities that can extend the base Identity type to suit needs that are specific to your application.

' Getting the username of the current userResponse.Write (User.Identity.Name) ROLESRoles are simply a comma-delimited String of role names that are added to the Principal to associate the current user with a role/s. ' Creating a string of rolesDim roleString() As String = {"manager", "cleaner"} PrincipalsA Principal contains information about the identity and role/s that the current user is associated with. It is through the Principal that you are able to check the role membership of the current user. In many ways a Principal is the glue that binds identities, roles, and the various other pieces of information that fully describe that Principal to the application.

A Principal is encapsulated by classes found in the System.Security.Principal Namespace. This namespace contains two Classes: GenericPrincipal and WindowsPrincipal through which you can determine the properties of a principal; and one interface IPrincipal that you can use to define your own custom Principals.

The .NET runtime uses the Principal that is attached to the current thread to gain information about the identity and roles of a user when handling requests that require authorization. To programmatically assign your own principal settings you simply create an instance of the Principal class passing in an identity object and a comma delimited string of roles for that identity. The constructor for the Principal object looks like this:

Public Sub New( _ ByVal identity As IIdentity, _ ByVal roles() As String _)

Therefore at the time of authentication you might do something like this to add an authenticated user to a principal, assign it some roles, and attach it to the current thread.

Creating your own roles

Page 21: Security Features in ASP

' Global.asax event handler that fires upon attempting to authenticate the userSub Application_AuthenticateRequest(ByVal sender As Object, ByVal e As EventArgs) If Request.IsAuthenticated() Then ' create an array of roles for the current user ' these would most likely be dynamically read ' from the data store for each user. Dim arrRoles() As String = {"Manager", "Cleaner"} ' Add our Principal to the current context Thread.CurrentPrincipal = New GenericPrincipal(Context.User.Identity, arrRoles) End IfEnd Sub

This only needs to be done once because the runtime automatically copies a reference to the principal object from the calling thread to the CallContext of the new thread.

If you cast your mind back to how FormsAuthentication works, you will remember that a user is authenticated and then an authentication cookie attached to the validating Response when you call one of the appropriate static methods of the FormsAuthentication provider. It is at that moment that the Application_AuthenticateRequest handler is called. When authenticating users you do not have to do anything in this handler, nor do you need to explicitly create a new instance of the GenericPrincipal class. However, to dynamically assign custom roles to a user (which is what we are interested in today) you do need to, and the Application_AuthenticateRequest handler is the ideal place to do this.

Bringing it All TogetherI'll stop here briefly, before we move onto the really cool stuff, to summarize the five steps needed to allow your application to implement role based checking:

1. Validate the User - check the users credentials against a data store of credentials.2. Create an Identity

Dim objIdentity As GenericIdentity = New GenericIdentity("txtUsername") 3. Get the roles for the current user

Dim strRoles() As String Dim arrRoles As New ArrayList() ' do some database call that returns a reader While reader.Read() arrRoles.Add(reader("role")) End While strRoles = arrRoles.ToArray(GetType(String), String())

4. Add the Identity and the Roles to a Principal Dim objPrincipal As GenericPrincipal = New GenericPrincipal(objIdentity, strRoles)

5. Add the Principal to the current context of the current thread

Thread.CurrentPrincipal = objPrincipal

Page 22: Security Features in ASP

Using RolesOnce you have authenticated a user and defined their identity and roles there are four ways that you can interact with the Principal to enforce permissions based on memberships within the application:

1. Configuratively 2. Programmatically 3. Imperatively 4. Declaratively

ConfigurativelyYou can configure the authorization and/or the location elements within the Web.config configuration files to grant or deny access to entire areas within the application outright, as opposed to the other 3 methods which suit a more piecemeal approach.

For example, in the application that we are developing it may be necessary to ensure that only users acting as System Administrators or Moderators are allowed access to certain administrative screens. To demonstrate this, let's presume that all of the forms that allow users to moderate forum posts reside under a directory called "ForumAdmin". Rather than programatically checking the role of a user inside every file that sits in that directory, you can simply configure the Web.config file for that folder to do the checking for you.

The following snippet excludes all users except for System Administrators or Moderators from accessing files in the directory that the Web.config file resides in (as well as its subdirectories):

' Snippet from Web.config<authorization> <deny users="*" /> <allow roles="SysAdmin, Moderator" /></authorization>

By placing the abovementioned Web.config at the root of the ForumAdmin directory, the application itself will inspect the roles of the user making the Request to determine whether access is granted. That's right, no additional code is neccessary, regardless of how many .aspx files are placed under that folder. (Compare that to classic ASP and the Session-based approach, where every "sensitive" page needs to have a check at the top of the page to determine if the user has rights to view the page...) Even from this simple example, you should get an idea of how this new approach simplifies the task of authorization, and, how it supersedes the methods available under the current practices of classic ASP.

ProgrammaticallyAlternatively, you may have directories that contain files that will be accessed by users acting in a wide variety of roles. An example of this would be the directory that displays the actual forum itself. You need to allow viewing access to all areas of the forum, even to unauthenticated members of the public, but to create a new post, it is imperative that a user not be in the role of Public or Other.

Page 23: Security Features in ASP

In your code, whenever you need to check to see if the user is in a role you simply query the IsInRole method of the current user. Let's look at the code snippet responsible for displaying the link to create a new forum post:

If Not (User.IsInRole("Public")) And Not (User.IsInRole("Other")) Then ' Display the linkElse ' Don't display it!End If

Or said in another manner:

If Not (Thread.CurrentPrincipal.IsInRole("Public")) _And Not (Thread.CurrentPrincipal.IsInRole("Other")) Then

' Display the linkElse ' Don't display it!End If ImperativelyYou can also imperatively demand that a user be in a role to access code by creating an instance of the PrincipalPermission class, configuring it with the user and role that you are checking for, then call the Demand method of that object to do the check. If the check fails, a SecurityException is raised. This is the previous example re-written to use imperative checking: Dim objPermission As New PrincipalPermission(User.Identity.Name, "manager")

Try objPermission.Demand() Catch ex As SecurityException ' Don't display it!End Try

The downside to the two previous methods is that if you are calling a method several times from different parts of the application, you need to repeat this logic all over the place.

DeclarativelyAs many of you would know, one of the great benefits of using Stored Procedures in the database is that you can enforce permissions specific to an individual stored procedure. With declarative checks you can bind permissions to an actual method (or event, or whatever) using meta-data attached to each specific object that requires it. For our purposes, let us assume that we have a method called dismissModerator(). Now, for obvious reasons, we do not want the moderator, or anyone else for that matter, to be able to call this method! Therefore, only users who are in the role of System Administrator can access this method. Let's set it up: ' Create a method that disables all moderator permissions' and attach a PrincipalPermissionAttribute to it that issues' a Demand.

Page 24: Security Features in ASP

<PrincipalPermissionAttribute(SecurityAction.Demand, Name:="smith", Role:="SysAdmin")> _Public Sub DismissModerator() ' logic hereEnd Sub

And now, to call it:

Try DismissModerator()Catch ex As SecurityException ' do something elseEnd Try

What has happened here is that the Permission check that is bound to the DismissModerator() Sub is carried out before execution of the Sub takes place. As you can see, this method of authorization is good, because you are enforcing the policy on an actual object, meaning that a developer cannot accidentaly call the method and inadvertently dismiss the poor forum moderator, because the object itself does the role checking. You can enforce declarative checking at class, class member, property or even event level. If you define a permission attribute on a class as well as one of its members the declaration at member level overrides the declaration at class level.

SummaryIn this article we've had a brief look at what role based security is and how the .NET runtime can assist in implementing it in our solutions. If you found this article interesting I'd encourage you to delve further into the System.Security.Permissions namespace where you'll find even more classes to assist you in producing a customized solution. Pay particular attention to the Union method of the PrincipalPermission class which allows you to bind multiple principal permissions to create a new permission.

Creating your own roles

' Global.asax event handler that fires upon attempting to authenticate the userSub Application_AuthenticateRequest(ByVal sender As Object, ByVal e As EventArgs) If Request.IsAuthenticated() Then ' create an array of roles for the current user ' these would most likely be dynamically read ' from the data store for each user. Dim arrRoles() As String = {"Manager", "Cleaner"} ' Add our Principal to the current context Thread.CurrentPrincipal = New GenericPrincipal(Context.User.Identity, arrRoles) End IfEnd Sub

Page 25: Security Features in ASP

This only needs to be done once because the runtime automatically copies a reference to the principal object from the calling thread to the CallContext of the new thread.

If you cast your mind back to how FormsAuthentication works, you will remember that a user is authenticated and then an authentication cookie attached to the validating Response when you call one of the appropriate static methods of the FormsAuthentication provider. It is at that moment that the Application_AuthenticateRequest handler is called. When authenticating users you do not have to do anything in this handler, nor do you need to explicitly create a new instance of the GenericPrincipal class. However, to dynamically assign custom roles to a user (which is what we are interested in today) you do need to, and the Application_AuthenticateRequest handler is the ideal place to do this.

Bringing it All TogetherI'll stop here briefly, before we move onto the really cool stuff, to summarize the five steps needed to allow your application to implement role based checking:

1. Validate the User - check the users credentials against a data store of credentials.2. Create an Identity

Dim objIdentity As GenericIdentity = New GenericIdentity("txtUsername") 3. Get the roles for the current user

Dim strRoles() As String Dim arrRoles As New ArrayList() ' do some database call that returns a reader While reader.Read() arrRoles.Add(reader("role")) End While strRoles = arrRoles.ToArray(GetType(String), String())

4. Add the Identity and the Roles to a Principal Dim objPrincipal As GenericPrincipal = New GenericPrincipal(objIdentity, strRoles)

5. Add the Principal to the current context of the current thread

Thread.CurrentPrincipal = objPrincipal

Using RolesOnce you have authenticated a user and defined their identity and roles there are four ways that you can interact with the Principal to enforce permissions based on memberships within the application:

1. Configuratively 2. Programmatically 3. Imperatively 4. Declaratively

ConfigurativelyYou can configure the authorization and/or the location elements within the Web.config

Page 26: Security Features in ASP

configuration files to grant or deny access to entire areas within the application outright, as opposed to the other 3 methods which suit a more piecemeal approach.

For example, in the application that we are developing it may be necessary to ensure that only users acting as System Administrators or Moderators are allowed access to certain administrative screens. To demonstrate this, let's presume that all of the forms that allow users to moderate forum posts reside under a directory called "ForumAdmin". Rather than programatically checking the role of a user inside every file that sits in that directory, you can simply configure the Web.config file for that folder to do the checking for you.

The following snippet excludes all users except for System Administrators or Moderators from accessing files in the directory that the Web.config file resides in (as well as its subdirectories):

' Snippet from Web.config<authorization> <deny users="*" /> <allow roles="SysAdmin, Moderator" /></authorization>

By placing the abovementioned Web.config at the root of the ForumAdmin directory, the application itself will inspect the roles of the user making the Request to determine whether access is granted. That's right, no additional code is neccessary, regardless of how many .aspx files are placed under that folder. (Compare that to classic ASP and the Session-based approach, where every "sensitive" page needs to have a check at the top of the page to determine if the user has rights to view the page...) Even from this simple example, you should get an idea of how this new approach simplifies the task of authorization, and, how it supersedes the methods available under the current practices of classic ASP.

ProgrammaticallyAlternatively, you may have directories that contain files that will be accessed by users acting in a wide variety of roles. An example of this would be the directory that displays the actual forum itself. You need to allow viewing access to all areas of the forum, even to unauthenticated members of the public, but to create a new post, it is imperative that a user not be in the role of Public or Other.

In your code, whenever you need to check to see if the user is in a role you simply query the IsInRole method of the current user. Let's look at the code snippet responsible for displaying the link to create a new forum post:

If Not (User.IsInRole("Public")) And Not (User.IsInRole("Other")) Then ' Display the linkElse ' Don't display it!End If

Or said in another manner:

Page 27: Security Features in ASP

If Not (Thread.CurrentPrincipal.IsInRole("Public")) _And Not (Thread.CurrentPrincipal.IsInRole("Other")) Then

' Display the linkElse ' Don't display it!End If ImperativelyYou can also imperatively demand that a user be in a role to access code by creating an instance of the PrincipalPermission class, configuring it with the user and role that you are checking for, then call the Demand method of that object to do the check. If the check fails, a SecurityException is raised. This is the previous example re-written to use imperative checking: Dim objPermission As New PrincipalPermission(User.Identity.Name, "manager")

Try objPermission.Demand() Catch ex As SecurityException ' Don't display it!End Try

The downside to the two previous methods is that if you are calling a method several times from different parts of the application, you need to repeat this logic all over the place.

DeclarativelyAs many of you would know, one of the great benefits of using Stored Procedures in the database is that you can enforce permissions specific to an individual stored procedure. With declarative checks you can bind permissions to an actual method (or event, or whatever) using meta-data attached to each specific object that requires it. For our purposes, let us assume that we have a method called dismissModerator(). Now, for obvious reasons, we do not want the moderator, or anyone else for that matter, to be able to call this method! Therefore, only users who are in the role of System Administrator can access this method. Let's set it up: ' Create a method that disables all moderator permissions' and attach a PrincipalPermissionAttribute to it that issues' a Demand.

<PrincipalPermissionAttribute(SecurityAction.Demand, Name:="smith", Role:="SysAdmin")> _Public Sub DismissModerator() ' logic hereEnd Sub

And now, to call it:

Try DismissModerator()Catch ex As SecurityException ' do something else

Page 28: Security Features in ASP

End Try

What has happened here is that the Permission check that is bound to the DismissModerator() Sub is carried out before execution of the Sub takes place. As you can see, this method of authorization is good, because you are enforcing the policy on an actual object, meaning that a developer cannot accidentaly call the method and inadvertently dismiss the poor forum moderator, because the object itself does the role checking. You can enforce declarative checking at class, class member, property or even event level. If you define a permission attribute on a class as well as one of its members the declaration at member level overrides the declaration at class level.

SummaryIn this article we've had a brief look at what role based security is and how the .NET runtime can assist in implementing it in our solutions. If you found this article interesting I'd encourage you to delve further into the System.Security.Permissions namespace where you'll find even more classes to assist you in producing a customized solution. Pay particular attention to the Union method of the PrincipalPermission class which allows you to bind multiple principal permissions to create a new permission.

ASP.NET 2.0

The Provider Model

If you've downloaded and used the ASP.NET Starter Kits available from www.asp.net,

the Provider Model and its implementation probably won't have come as too much of a

shock. Microsoft began to employ the "Provider Design Pattern" in its Starter Kits in the

summer of 2002, but didn't officially formalize it as a model until the development of

ASP.NET 2.0's Personalization feature.

Without boring you with the specifics, let me generalize by saying that because of the

Provider Model, security in ASP.NET 2.0 is much more simplistic, easy to configure, and

quick to implement than it was previously. The model assumes the configuration of

users and roles by automatically creating a database within SQL Server (or, if you choose

to use Access, as an .MDB file within the Data folder of your application). Immediately,

you're able to start to register and authenticate users against this newly created table.

Gone are the days of having to build the database schema by hand, and then having to

tailor each Web application to work in its respective database schema.

Page 29: Security Features in ASP

The Provider Model can be broken into two distinct security providers: the Membership

Provider and the Role Provider. The Membership Provider is used to store usernames

and passwords; the Role Provider is used to store -- you guessed it -- user roles.

Out of the box membership providers include the default AccessMembershipProvider,

the SqlMembershipProvider, and an abstract MembershipProvider class. You can use

this to create your own Membership Provider if, for instance, you need to store

usernames and passwords within an XML file, or validate credentials via a Web service.

For the sake of simplicity, we'll use the default AccessMembershipProvider throughout

this article.

The AccessMembershipProivder, like the SqlMembershipProvider, stores usernames

and passwords within a database. The AccessMembershipProivder, however, stores this

information within an Access database that's created for you automatically within the

Data folder of your application. Whenever you create a new Web application, the

AccessMembershipProivder automatically will create everything you need to start

registering and authenticating users.

Configure Security Using the Website Administration Tool

Configuring your applications to use ASP.NET 2.0 security is a simple three-step process.

First, we create a new Website within either Visual Studio 2005 beta or Visual Web

Developer 2005 Express beta, and ensure that Website is turned into an application

within IIS. Second, we use the Web Site Administration Tool to enable and configure

security for the newly created application. Finally, we use controls available in the suite

of Login controls to build the UI with which our users will interact.

To demonstrate this simplicity and, most importantly, flexibility, let's start by creating a

new Website. Follow these steps:

1. Open either Visual Studio 2005 beta or Visual Web Developer 2005 Express beta.

2. Select File, New Web Site.

3. Select the ASP.NET Web Site Template.

4. Choose a Website name and path within the Location text box and click OK. For

this article, I'll call mine Dorknozzle.

5. You may want to take this time to rename your default Web form login.aspx.

Page 30: Security Features in ASP

6. Now that the Website has been created, convert the site into an application. First,

open IIS.

7. Next, expand your computer name, expand the Websites folder, expand the

Default Web Site node, and locate your newly created site.

8. Right click the Website and choose Properties.

9. Select the Create button from the Directory tab and click OK.

10. Close IIS.

Now that your Web application has been created and configured, you're ready

to enable and configure security via the Web Site Administration Tool. Again,

the Web Site Administration Tool is nothing more than a set of pre-built

ASP.NET 2.0 pages and resources that reside within the C:\Inetpub\wwwroot\

aspnet_webadmin\2_0_40607 directory. To enable and configure security,

open the Web Site Administration Tool for your newly created Web application:

navigate to the application's URL and add the WebAdmin.axd file to the end of

the URL. In my case, the URL string will look like this:

http://localhost/Dorknozzle/WebAdmin.axd

If you're using Visual Studio 2005 beta or Visual Web Developer 2005 Express

beta, you can also select ASP.NET Configuration from the Website menu. Either

way, the Web Site Administration Tool will appear.

Immediately switch to the Security tab. Your screen will look like this:

Page 31: Security Features in ASP

1387_image1 (click to view image)

As you can see, security is divided into three core groups within the Web Site

Administration Tool: Users, Roles, and Access Rules. If you are new to

configuring security within the Web Site Administration Tool, it may be easier to

simply select the link that reads, "To configure security step by step, use the

Security Setup Wizard". This launches the Security Setup Wizard's Welcome

screen. To begin the configuration process, select the Next button located near

the bottom right of the browser window to advance to Step 2.

Step 2 allows you to choose the authentication type. If you're using Windows

authentication (default), simply click next. To work with Forms authentication

(as we're doing in this article) click the "From the Internet" option and choose

Next.

Step 3 displays the default provider "AspNetAccessProvider" mentioned earlier

in this article. Because the Access Provider is the default provider, we needn't

configure this option here. Simply choose Next.

Step 4 enables roles-based authentication for an application. If you were

working with roles, you'd enable this checkbox and click Next. Configuration of

Page 32: Security Features in ASP

roles would be handled within the Security tab in the main menu. For now,

leave the checkbox unchecked and click Next.

Step 5 is where the real fun begins. This is where you can add users to your

application, auto-generate passwords, send the passwords via email, and

activate the users. To keep this example simple, I'll enter some basic

information, outlined below, and click Create User.

1387_image2 (click to view image)

Once you've added the user, you have the option to choose Continue, to create

more users, or Next, to advance to the Next screen. I'll add two more users and

then click Next.

Step 6 allows you to configure rules to apply to particular users. For instance,

since the user "zak" is an administrator, he'll be given full access. However, if I

had various departments within my Web application, I could configure certain

users to be allowed access only within their department folder. I won't

configure any rules at this time, so I'll click Next.

Page 33: Security Features in ASP

Step 7 alerts you that you've finished enabling and configuring security for your

Web application. To complete the wizard, select Finish -- you'll be taken back to

the Security tab in the main menu.

Now that you're done, you can go ahead and close the Web Site Administration

Tool.

Automatically, the AccessMembershipProvider creates a Microsoft Access

database file called AspNetDB within your application's Data folder. Open the

database file to examine its structure. As you can see below, ten tables are

created, including the aspnet_Users table, which includes generic user

information, and the aspnet_Membership table, which contains detailed user

credential information including the user's hashed password and salt.

1387_image3 (click to view image)

For more information on hashing and salting passwords, see the SitePoint

article, "Securing Passwords in Your Database".

Using Login Controls

As I mentioned earlier, some of the most exciting controls to be added to the

collection of already-robust ASP.NET controls are contained in the suite known

Page 34: Security Features in ASP

as the Login controls. The Login controls, which include the Login, LoginView,

PasswordRecovery, LoginStatus, LoginName, CreateUserWizard, and

ChangePassword controls, allow quick, seamless integration between ASP.NET

2.0 security and your Web applications.

Tightly integrated with the Provider Model, Login controls take full advantage of

the configured provider. For instance, if you configured your application to use

the AccessMembershipProvider (which is the default), you could easily add to

your page a Login control that would automatically validate a user against the

AspNetDB Access database located within your applications Data folder.

Alternatively, if you configured your application to use the

SqlMembershipProvider, the configured Login controls would validate users

against a SQL database instead.

The Login Control

Now that you have a grasp on the Provider Model, AccessMembershipProvider,

and have enabled and configured your site via the Web Site Administration Tool

to use authentication, let's build the UI with which your users can interact. As

I've already mentioned, ASP.NET 2.0 includes a suite of Login controls

spearheaded by the Login control. The Login control provides the necessary

interface through which a user can enter their username and password. At its

most basic level of functionality, a Login control can easily be added to the page.

Just include the following markup within a Web form:

<asp:Login id="lcDorknozzle" runat="server"/>

The control renders as a basic login page similar to that shown below.

Page 35: Security Features in ASP

1387_image4 (click to view image)

While the Login control exposes myriad properties, some of which I'll go over

briefly, the great part of about it lies in the fact that only the DestinationPageUrl

property really needs to be configured. When it's set, this property

automatically redirects the user to a destination page. Knowing this, we could

configure our Login control to resemble the following:

<asp:Login

id="lcDorknozzle"

runat="server"

DestinationPageUrl="index.aspx"/>

In this case, if the users entered valid credentials, they would automatically be

redirected to index.aspx. Other important properties include the ability to offer

a customized error message when users enter the wrong credentials. This

property, the FailureText property, is by default set to read, "Your login attempt

was not successful. Please try again." You may also want automatically to

redirect the user to a page that allows them to create a new user or even

recover a lost password. In this case, you would configure the CreateUserText,

CreateUserUrl, PasswordRecoveryText, and PasswordRecoveryUrl properties as

follows:

Page 36: Security Features in ASP

<asp:Login

id="lcDorknozzle"

runat="server"

DestinationPageUrl="index.aspx"

CreateUserText="New User?"

CreateUserUrl="newuser.aspx"

PasswordRecoveryText="Forget Your Password?"

PasswordRecoveryUrl="forgotpassword.aspx"/>

In this case, the control would render in the browser similar to the image shown

below.

1387_image5 (click to view image)

The flexibility of the Login control doesn't stop there. Aside from the dozens of

other properties that can be used to customize the control's functionality, the

Login control also supports Theming via the EnableTheming property,

customized CSS classes via the CssClass property, and basic formatting through

the dozens of style properties associated with each control available in the

ASP.NET framework. In fact, if you're using either Visual Studio 2005 beta or

Visual Web Developer 2005 Express beta, you can simply right-click the control,

select Auto Format…, and pick a style from a pre-defined list displayed in the

Page 37: Security Features in ASP

Auto Format dialog box. I picked the Elegant style, which renders similarly to

this:

1387_image6 (click to view image)

The LoginName and LoginStatus Control

Once the user has logged in, you may want to utilize either the LoginName

and/or LoginStatus control. These two useful controls allow you to display

relevant information regarding the authentication status of a user. The

LoginName control, for instance, allows you simply to display the username of

the authenticated user:

<asp:LoginName id="lnUser" runat="server"/>

The LoginStatus control, on the other hand, allows the user to log in or log out

of your application. It resembles the following:

<asp:LoginStatus id=" lsUser" runat="server"/>

To see these controls in action, I'll add them to my index.aspx page (the page at

which the user arrives once they've logged in):

Page 38: Security Features in ASP

<form runat="server">

Welcome <asp:LoginName id="lnUser" runat="server"/>, your login was

successful!<br /><br />

<asp:LoginStatus id="lsUSer" runat="server"/>

</form>

When users log in now, they are presented with a customized message that

contains their names, along with the ability to log out if they choose. The output

renders in the browser as shown below.

1387_image7 (click to view image)

The LoginStatus control will allow users to log out if they are currently logged in,

and will display a link to the login page if they're logged out.

The LoginView Control

Another useful Login control is the LoginView control. This control allows you to

customize information that will be shown to users through templates, based on their

roles. For instance, you may decide that Administrators are able to see a complete

department list once they enter the application, but that someone who belongs to a

specific department -- let's say it's Engineering -- only sees information that relates to

the company and the Engineering department. You can also use the LoginView control

to display customized information based on users' login status. For instance, if an

anonymous user visits your site, you might want to alert them that the site is intended

for registered users, and perhaps let them know that they can click the New User link

Page 39: Security Features in ASP

to register. Alternatively, you may want to alert logged-in users that they don't need

to log in again. You might even show them a "welcome back" message, complete with

their name, using the LoginName control discussed earlier.

To use the LoginView control, you would simply add the control to the page using the

following syntax:

<asp:LoginView id="lvDorknozzle" runat="server">

</asp:LoginView>

Of course, without the use of templates, the control is fairly useless. In this case, we'll

make sure that anonymous users are told to register by clicking the New User link,

and that logged-in users see a notification that they've already been logged in. Add

the following LoggedInTemplate and AnonymousTemplate child tags to the LoginView

parent tag:

<asp:LoginView id="lvDorknozzle" runat="server">

<LoggedInTemplate>

Welcome <asp:LoginName id="lnUser" runat="server"/>

</LoggedInTemplate>

<AnonymousTemplate>

Welcome to the Dorknozzle site!<br />

Please click on the New User link to register on our site.

</AnonymousTemplate>

</asp:LoginView>

Now, when users visit the login.aspx page for the first time, they are considered

anonymous and are presented with the welcome message similar to the one shown

here.

Page 40: Security Features in ASP

1387_image8 (click to view image)

You could configure the LoginView control further by displaying customized messages

depending on users' roles. For instance, I could add within the LoginView tag the

RoleGroups tag. To this, I'd add a RoleGroup control in which the name of the Role

was a value of the Roles attribute:

<asp:LoginView ID="lvDorknozzle" Runat="server">

<RoleGroups>

<asp:RoleGroup Roles="Engineering">

<ContentTemplate>

You are a member of the Engineering department.

</ContentTemplate>

</asp:RoleGroup>

</RoleGroups>

<LoggedInTemplate>

Welcome <asp:LoginName ID="lnUser" Runat="server" />

</LoggedInTemplate>

Page 41: Security Features in ASP

<AnonymousTemplate>

Welcome to the Dorknozzle site!<br />

Please click on the New User link to register on our site.

</AnonymousTemplate>

</asp:LoginView>

The CreateUserWizard Control

Chances are that if you went through the process of creating new users via the Web

Site Administration Tool, you've already used the CreateUserWizard control and may

not even have known it. The CreateUserWizard control simply allows a new user to

add themselves (or register) to your Web application. This powerful tag offers many

customizable features, but can quickly be added to and used in your site via the

following tag:

<asp:CreateUserWizard id="NewUserWiz" runat="server">

</asp:CreateUserWizard>

In the browser, the page renders similar to that shown below.

Page 42: Security Features in ASP

1387_image9 (click to view image)

Of course, the true power in the CreateUserWizard control lies in its flexibility. The

control offers seven templates (HeaderTemplate, SideBarTemplate,

StartNavigationTemplate, StepNavigationTemplate, FinishNavigationTemplate, Sign

Up For a New Account Template, and a Complete Template) that can be customized

according to your needs. Even better, the CreateUserWizard control allows you

automatically to send an email to newly registered users simply by adding the

MailDefinition tag as follows:

<asp:CreateUserWizard id="CreateUserWizard1" runat="server">

<MailDefinition

BodyFileName="NewUserEmail.txt"

From="[email protected]"

Subject="Welcome to the Dorknozzle site!"/>

</asp:CreateUserWizard>

Page 43: Security Features in ASP

Once a new user is added to the site, an email is sent to that user. That email, defined

within a text file, is loaded via the BodyFileName property, as shown in the code

above. Variables can be customized simply with the addition of special expressions,

such as <% UserName %>, to the text file.

Finally, in order for the email to be relayed, the email server must be specified in the

<smtpMail> mail section of the Web.config file:

<configuration>

<system.web>

<authentication mode="Forms"/>

<smtpMail serverName="Localhost"/>

</system.web>

</configuration>

The PasswordRecovery Control

As an administrator of a Web application, the last things you want to do are answer

phone calls and respond to emails for people who have forgotten their passwords.

The PasswordRecovery control can ease this burden. By default, you can add the

following tag, which allows users to enter their user names and answer their secret

questions. In turn, an email message is generated with each user's password, and

sent:

<asp:PasswordRecovery id="prForgotPass" runat="server"> </asp:PasswordRecovery>

In the browser, the PasswordRecovery control renders like so:

Page 44: Security Features in ASP

1387_image10 (click to view image)

Once users enter valid user names, they must answer their secret questions. In the

browser, the page looks like that shown below.

1387_image11 (click to view image)

Page 45: Security Features in ASP

Similar to the CreateUserWizard control, the mail formatting is handled within the

MailDefinition tag:

<asp:PasswordRecovery id="prForgotPass" runat="server">

<MailDefinition

BodyFileName="forgotpassword.txt"

From="[email protected]"

Subject="Word has it, you forgot your password?"/>

</asp:PasswordRecovery>

If everything is formatted correctly, the email will be sent and a message will appear

to the user similar to this:

1387_image12 (click to view image)

The ChangePassword Control

Finally, The ChangePassword control, as you might expect, allows users to change

their passwords. The ChangePassword control can be added to any page with the

following tag:

<asp:ChangePassword id="cpChangePass" runat="server"/>

In the browser, the control renders similar to this:

Page 46: Security Features in ASP

1387_image13 (click to view image)

Like the CreateUserWizard and PasswordRecovery controls, the ChangePassword

control can be configured, via the MailDefinition tag, to send a confirmation email to

users once they've successfully changed their passwords. Unlike the CreateUserWizard

and PasswordRecovery controls, however, the ChangePassword control requires that

users are logged in before they can change their passwords.

The Membership API

In certain instances when working with security, you'll need more flexibility than is

provided either by the Web Site Administration Tool or the Login controls. In this case,

you'll want to work directly with the Membership API. Exposed through the

Membership class, the Membership API allows you to create users, change passwords,

and search for users based on specific criteria, programmatically. For the most part, the

Login controls we've seen so far use the methods exposed by the Membership class

anyway; your ability to use these directly from code is an added bonus. The following

methods exposed by the Membership class are the ones you may find yourself using

most often:

CreateUser - Allows you to creates new users

DeleteUser - Allows you to delete existing users

Page 47: Security Features in ASP

FindUsersByEmail - Allows you to retrieve a set of users that match an email

address

FindUsersByName - Allows you to retrieve a set of users that match a certain

username

GeneratePassword - Allows you to generate a random password

GetAllUsers - Allows you to retrieve all users stored in the Membership Provider

GetNumberOfUsersOnline - Allows you to return the number of users currently

logged on

GetUser - Allows you to retrieve the membership information associated with the

current or supplied user

GetUsernameByEmail - Allows you to retrieve a username for a user with a certain

email address

UpdateUser - Allows you to update a particular user's information

ValidateUser - Allows you to authenticate a user against the Membership Provider

To demonstrate the flexibility of these methods, I'll add some text and a Label

control to my index.aspx as follows:

Number of Users Online:

<asp:Label id="lblNumUsersOnline" runat="server"/>

In my code-behind, I'll add some code that accesses the number of users online:

Sub Page_Load(s As Object, e As EventArgs) Handles MyBase.Load

lblNumUsersOnline.Text = _

Membership.GetNumberOfUsersOnline().ToString()

End Sub

I could also add a GridView control to the page like so:

<asp:GridView id="gvUsers" runat="server" AutoGenerateColumns="False">

<Columns>

<asp:BoundField HeaderText="Username" DataField="Username" />

<asp:BoundField HeaderText="Is Online?" DataField="IsOnline" />

<asp:BoundField HeaderText="Is Approved?" DataField="IsApproved" />

<asp:BoundField HeaderText="Email" DataField="Email" />

Page 48: Security Features in ASP

</Columns>

</asp:GridView>

In the code-behind, I could add the following to my Page_Load event handler to

fill the grid:

gvUsers.DataSource = Membership.GetAllUsers()

gvUsers.DataBind()

The output renders in the browser similar to the below.

1387_image14 (click to view image)

Conclusion

ASP.NET 2.0 builds on an already feature-rich framework by adding enhanced

security features.

In this article, we focused on the new Provider Model exposed by the .NET

Framework 2.0. Next, we looked at the suite of Login controls that you can take

Page 49: Security Features in ASP

advantage of when building your Web applications. Finally, we looked at the

Membership API and the methods exposed by the Membership class. Whether

you use some or all of the security features offered within the newest release of

ASP.NET is up to you, but I, for one, think there's a great deal to be excited

about in ASP.NET 2.0.