Secure Your Mobile Apps
Use forms authentication to secure ASP.NET mobile applications.
by Doug Thews
April 2003 Issue
Technology Toolbox: VB.NET, SQL Server 2000, ASP.NET
An often-overlooked ASP.NET feature is its built-in security plumbing, which you can use to secure any application easily with a minimal amount of coding. Providing integrated security in your ASP.NET application is a crucial element in preventing unauthorized access to your corporate data, while building customer confidence in the security of your company's business systems. In this article, I'll guide you through different ways to use forms authentication to secure your mobile applications.
ASP.NET makes securing applications much simpler than it was in Active Server Pages (ASP). It offers the plumbing for Web security, one portion of which is called forms authentication. Forms authentication is a cookie-based authentication process handled by ASP.NET, which allows you to replace the standard login screen and authentication business logic with your own customized version. ASP.NET handles the process of authenticating users automatically for each page request by enabling forms authentication on a Web or virtual directory. You no longer need to spend time putting additional script code or include files in your Web pages to check for this authentication manually.
ASP.NET provides three different types of authentication right out of the box: Windows-based authentication, Passport authentication, and forms authentication, which this article will focus on. Forms authentication is best suited for secure ASP.NET applications, because it doesn't restrict you from using any authentication source, such as an internal customer relationship management (CRM) or directory server. With forms authentication, ASP.NET sends all nonauthenticated user requests to a standard login page that you specify, and it handles the authentication process there. This provides the maximum amount of flexibility, because you're now in charge of authenticating the user against any data source you want.
Take a quick look at how ASP.NET processes incoming Web requests for a Web that's been secured with forms authentication. When users make a new Web request, ASP.NET checks to see if that user session has a valid authentication cookie for this Web. If not, ASP.NET redirects the user to the login page specified in the configuration process (more on that later).
You can perform forms authentication for both mobile and standard ASP.NET Web applications (see Figure 1 for the authentication process). You use the FormsAuthentication base class for all ASP.NET forms authentication. The MobileFormsAuthentication class has two unique methods—SignOut and RedirectFromLoginPage—that are designed specifically to support cookieless devices by appending appropriate authentication information to the appropriate URLs. Both methods are fairly interchangeable.
Configure Forms Authentication
Enable forms authentication (both mobile and standard) by editing the web.config file for the Web site or virtual directory you want to secure. Web.config is an XML data file that contains ASP.NET configuration settings for the virtual directory the file is in. ASP.NET reads this file to determine its processing settings specific to an application or virtual directory. It overrides any settings from the master.config, which is the root configuration file for ASP.NET (found in %WINDIR%\Microsoft.NET\Framework\v1.0.3705\config; 1.0.3705 is the version of the .NET Framework currently installed). ASP.NET uses the settings from machine.config whenever you don't override them explicitly in a web.config for an application or virtual directory.
You can also secure subdirectories differently within this Web by using multiple web.config files. For example, you can have a Public subdirectory with no authentication, which contains a web.config with forms authentication turned off. You can then have a Private subdirectory, which contains a web.config file with forms authentication turned on. However, if your Web contains multiple folders, the web.config file at the current level takes precedence over a web.config file at the parent level. ASP.NET uses settings from the machine.config file if no web.config file exists for the current Web folder.
Enable and configure forms authentication by editing the web.config file and searching for the <authentication> section:
<authentication mode="Forms"
</authentication>
You must enter "Forms" exactly as shown because the entries in web.config are case-sensitive.
A <forms> section inside the <authentication> block contains all the configuration settings for forms authentication:
<forms name= "CookieName",
loginUrl="Login.Aspx"
protection =
"All|None|Encryption|Validation"
timeout="seconds",
path="CookiePath"
</forms>
The Name property is the name of the cookie that ASP.NET uses for authentication. The default is .ASPXAUTH, which is the value inherited from the MACHINE.CONFIG file for a default .NET installation. The loginUrl property specifies the ASP.NET login page that ASP.NET redirects to for requests that haven't been authenticated. Make sure the login page isn't in a directory that has protection set by the web.config file. The protection property specifies the level of protection ASP.NET uses during the authentication process. "All" specifies that both Encryption and Validation are used. The timeout property specifies how long (in seconds) the authentication cookie is valid within the current browser session; the default is 30 minutes. Setting a timeout value of zero makes the cookie persistent (providing a technique for user auto-login between browser sessions). The path property specifies the cookie's path. The default for this property is "/".
Within the forms section, you can also add a <credentials> section and multiple <users> subsections to store a list of users to authenticate against:
<credentials passwordFormat=
"Clear|Sha1|MD5"
<user name="username"
password="password" />
</credentials>
The passwordFormat property allows you to specify the level of encryption in which credentials are sent from the client to the server. You can enter each user's name and password within the <credentials> section. ASP.NET sends the password to the client using the encryption specified in the <credentials> section, and also stores it using the same encryption level in the web.config file. This makes the configuration file safer from compromise, but also makes it that much harder to maintain.
Don't Store Users
Storing your users might seem an easy way to create a forms authentication site, but I don't recommend it for production systems. Imagine the overhead for your site's administrators if you told them they needed to add, update, and delete entries in the web.config text file every time they needed to change security. I'll go into the authentication store in more detail later, but suffice it to say that you should take great care before using the <credentials> section for a production Web site.
Another configuration setting is the <authorization> section. This tells ASP.NET who is allowed access to this Web or virtual directory:
<authorization>
<allow|deny users = "*"|"?"|{user
list} />
<allow|deny roles = {role list} />
<allow|deny verbs =
"GET"|"HEAD"|"POST"|"DEBUG" />
</authorization>
Use the <deny users = "*"> statement if you want to challenge all users. Replacing the "*" with a "?" challenges only anonymous users. This section also allows you to specify roles to allow or deny, instead of providing a long list of users. You can also allow or deny various HTTP verb types within the <authorization> section. This provides you with the ability to lock down the Web based on certain client accesses (verbs).
One last configuration item to check is whether the current Web is set to cookieless mode. In this mode, the server-side cookie's session ID is passed in encrypted text as part of the querystring between page requests. ASP.NET appends this data to the end of the Web site URL (but before any other parameters). ASP.NET evaluates this information and ensures it's valid and not expired. If it's either not valid or expired, ASP.NET redirects the browser to the login page specified in the <Forms> section. If the client is redirected for authentication, ASP.NET appends a querystring variable called ReturnUrl that indicates where ASP.NET should return to if authentication passes.
Use cookieless mode to ensure support for the wireless/handheld devices that traditionally use mobile Web pages; these devices and their Internet gateways don't usually support cookies. Cookieless mode is enabled by default when you create a mobile Web forms application using Visual Studio .NET. See if cookieless mode is enabled by checking the web.config file and looking for the <sessionstate> section (within the <system.web> section):
<sessionstate mode="InProc"
cookieless="true" />
Now that you've enabled forms authentication for your Web application, it's time to create the standard login page that your Web application will call anytime an unauthenticated browser request is made to an ASP.NET page in this Web. (Remember that non-.NET resources, such as HTML or ASP pages, aren't secured through forms authentication.)
First, create a blank solution and Web project by opening VS.NET and selecting File | New | Blank Solution followed by File | New | Project. Select a Web project and specify the server and virtual directory to place the project in. Next, add a new mobile Web form page by choosing File | Add New Item and selecting Web Project Items | Mobile Web Form. After adding the page, open it up in the IDE and place two text fields on the page: one for the userID and one for the password. Then, add a Login command button to process the login request (see the ASP.NET code for creating the ASPX page in Listing 1).
Determine ID/Password Validity
Now, before you can authenticate a user, you must create the code that determines whether a userID/password pair is valid. I like to create this code as part of an overall object class, because it abstracts the authentication details from the login page. The login page should only have to know whether the authentication passed or not.
First, create a class file that describes your SecurityUser object (I'll use VB.NET for this example). To do this, open VS.NET and create a new blank solution called SecurityUser. Next, add a new VB.NET class item to the SecurityUser project. This object holds properties for a username and password, and also contains a single method for authenticating a user. Creating a central authentication method makes it easy to change the way authentication is performed (see Listing 2).
Now it's time to create a Validate method for your object. This method takes the userID and password pair of the current object (Me) and validates them against your security repository. To demonstrate this, I'll show you three possible scenarios for authentication. The first is authenticating against the data source specified in web.config's <credentials> section. The second scenario authenticates against a custom SQL Server database, such as one that might be found as part of a CRM system. The last example shows authentication against an Active Directory data source.
Authenticating against usernames and passwords defined in web.config's <credentials> section is one of the most common examples of forms authentication documented to date. Although this is easy to implement, it isn't as flexible or maintainable as authenticating against a separate data source.
Use the FormsAuthentication class's Authenticate method to authenticate against this data source. You can use this code to create a Validate method for your SecurityUser object that uses the Authenticate method to validate a username and password pair:
Public Function Validate() as Boolean
' Use the features of default forms
' authentication to match up the
' userID and password
Return(FormsAuthentication. _
Authenticate\
(Me.Name, Me.Password))
End Function
For this example, you don't need to use the MobileFormsAuthentication class, because you're validating only a userID and password against entries in web.config.
Authentication against a relational database is fairly straightforward. You'll use a SQL Server database for this example, but you can expand this concept easily to another data source, such as your company's CRM system.
In this example, you take the current User object's username and password values, and see if this exact pair exists in your database's Security table. In a production application, the SQL query would probably be part of a stored procedure, but I've purposely put the SQL query in the code as an example. You can replace the Validate method you used earlier with this code to authenticate against a SQL Server repository. This code assumes you have a table already called SECURITY that contains Name and Password columns (see Listing 3).
Another real-world example of custom authentication is the need to validate against an existing Active Directory. Although you could accommodate this through Windows authentication, forms authentication gives you more granular control over the authentication process. It also allows you to augment the user information from Active Directory with your own user information specific to this application in another database.
Authenticate Your User
Use the Lightweight Directory Access Protocol (LDAP) provider .NET provides to access Active Directory. Determine if the userID and password pair is valid by attempting to access an Active Directory object for the userID with the credentials entered. This process throws an error (which you need to trap with the Try … Catch mechanism) if the userID and password pair is invalid. You can assume the credentials are valid if ASP.NET doesn't throw an exception. You can replace the Validate method from your object with code to authenticate against a Windows 2000 Active Directory source (see Listing 4).
Now that you have a SecurityUser object that has a Validate method of your choice, you can add your login code to the Click event of the Login command button you placed on the Login ASPX page. The actual authentication takes place there. You need to call the Authenticate method in the Login button's event handler to authenticate your user. Do this by opening up the Login.vb file in VS.NET and entering code for the btnLogin Click event handler (see Listing 5).
Once the user is validated, invoke the RedirectFromLoginPage method. This method sets an authorization cookie for you associated with the username. The second parameter indicates whether you want the cookie persisted across sessions. If the user enters invalid credentials, you set the Visible property for an error label on the login page informing the user that invalid credentials were entered.
There's a bug in the RedirectFromLoginPage method as of .NET version 3705 (with Service Pack 1). If you attempt to store session information using Session or Cache and then invoke this method, that information is lost once the redirect is performed. Microsoft is aware of this bug and is working to correct it in a future service release.
You might want more granular control over the redirect process. For example, say that users should always go to a main page after they authenticate. This is sometimes a good practice, because you might not want the users to jump to an application's middle pages. To do this, replace the RedirectFromLoginPage method with these statements:
MobileFormsAuthentication. _
SetAuthCookie (objUser.Name, false)
' Put any business logic you want here
' and then go to the main page
Me.RedirectToMobilePage("main.aspx")
You can do a lot of other things with forms authentication besides just locking down a mobile ASP.NET application. Forms authentication uses two events you can intercept to perform user maintenance or other tasks: Application_AuthenticateRequest and Application_AuthorizeRequest. You can handle these events in the GLOBAL.asax file.
When a security module establishes the user's identity, the Application_AuthenticateRequest event signals that the request is ready to be authenticated. The Application_AuthorizeRequest event signals that the security module has authorized the request when a security module verifies user authorization. In addition to the Application_AuthenticateRequest and Application_AuthorizeRequest event handlers, you can also daisy-chain the original event handler with an asynchronous event handler by using the AddOnAuthenticateRequestAsync and AddOnAuthorizeAsync methods (see what you can do with forms authentication in the sidebars, "Use Forms Authentication Events" and "Use Security Information in Your Application").
As you can see, forms authentication is a powerful piece of ASP.NET plumbing that's built for you already and waiting for you to take advantage of it. You no longer need to expend development cycles at the beginning of every project to create a complex security infrastructure for your mobile ASP.NET applications. You can capitalize on the ASP.NET forms authentication architecture right away, with only a few lines of code, to provide customized authentication against your own security data source.
About the Author
Doug Thews is the director of software development for divine in Dallas. He has more than 17 years of software development experience, and he specializes in enterprise application development. Doug is blessed with a beautiful wife (Dana) and daughter (Stefanie). Reach Doug at .
|