![]() |
|
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Published: Wednesday, July 20, 2005 By Scott Mitchell
Introduction
There have been plenty of articles here on 4Guys as well as across the Web that discuss forms-based authentication in
ASP.NET. For more information see Darren Neimke's articles Using
Forms Authentication in ASP.NET and Role-Based
Authorization with Forms Authentication; also check out the User
Authentication section here on 4Guys. However, most of these articles focus simply on how to implement forms-based
authentication, topics such as what settings are required in With this article we will not be looking at how to implement forms-based authentication; rather, we will peel back the layers of forms-based authentication and examine what's really happening when a user is "authenticated." If you've ever wondered how, exactly, a user's authentication status is remembered as they visit various pages on the site, or how ASP.NET protects against nefarious users from circumventing the authentication process and "faking" a successful login without valid credentials, read on to learn more!
The Forms-Based Authentication Workflow From the end user's point of view, when visiting a site they are typically allowed to login by entering their name and password. Alternatively, if they attempt to visit a page that they need to be authenticated in order to access, they'll automatically be sent to the login page. At the login page, our end user will enter her credentials - typically a username and password - and click a button. Assuming their credentials are valid, they'll then be "logged on" to the site. Once our end user is logged on, she can visit any number of pages on the site and be remembered - that is, she need not re-enter her credentials unless she's closed her browser or explicitly logged out. (Some financial sites or sites that are commonly visited through public terminals will automatically log out a user after a period of inactivity.)
From our view as the page developer, implementing forms-based authentication requires setting up the This workflow is one both end users and most page developers are familiar with. What it fails to answer, however, is how, exactly, is a user "logged in?" As a user bumps from page to page in the site, how does the site remember that the user is, indeed, "logged in?".
Remembering That a User is Logged In
So how can we remember this data? One approach, and an approach used commonly in the days of classic ASP, would be to use
a session variable that would indicate whether or not a user had successfully logged in. (See the article
Simple Authentication for a look at using session variables
in a classic ASP setting for more information.) While this approach definitely works, one downside is that this login data
cannot be persisted across the length of a session. That is, with session variables the state is lost once a user's session
expires, which happens when they close their browser or are inactive for a duration greater than the site's session timeout.
But many sites that utilize forms-based authentication allow the end user to check a 'Remember Me' checkbox that allows the
user to login just once at their home computer and not need to re-enter their login credentials, even days later after
having shut down their computer. In fact, you can configure forms-based authentication to work in this manner. Both the
Clearly session variables are not at play with forms-based authentication; instead, cookies are used, which might have been
obvious enough given the fact that the method to login a user (
When determining what information we need to persist across page visits, we're really asking two questions: the first is, what information must we have to ensure that a user is, indeed, authenticated; the second is, what information do we need to correctly identify that, yes, this is user X? A naive approach to answering these two questions is, "Well, I'll simply store the user's credentials in the cookie." On each page request we could take the user's credentials passed down in the cookie and determine if they are valid, just like we did on the login page. Additionally, with their credentials handy we certainly can identify the user - we have their username and password, after all! When storing authentication information in a cookie, you have to be careful because this cookie data is passed over the wire in plain-text (unless your site uses SSL). Additionally, the cookie's contents reside as an unencrypted text file on the end user's computer. If you stored a user's credentials in a cookie, anyone who could access this computer or was sniffing the network traffic could easily peer into the cookie and learn the user's username and password. Ok, so if we don't want to store the user's credentials in a cookie, then what will we store? At minimum we need to store the logged in user's username, so we can identify who this authenticated user is. But if we just store this authenticated user's username in plain-text, the site can be easily compromised by a hacker. The problem with this plain-text approach is that a nefarious user can "bake" his own cookies - after all, the cookie's contents is a file on the client computer. So what's to stop a hacker from creating his own cookie that has any ol' person's username in it? Once our hacker has done this, they can log in as anyone they like! Clearly we need a better approach, one that can include the user's username but cannot be compromised or spoofed by hackers.
An Authentication Ticket - Encrypted and Verified for Your Convenience Answering the second question - how is this information protected from inspection or spoofing - ASP.NET, by default, both encrypts and validates the authentication ticket. That is, the contents of the authentication ticket cookie are encrypted when the cookie is written to the client and, each time its sent to the server, is decrypted back and inspected. The authentication ticket is also validated by default. Validation is accomplished by a MAC, or Machine Authentication Check. This is accomplished by computing a digest hash of the concatenation of the contents of the authentication ticket and tacking on a secret key that is known only to the web server. This hashed value is then appended to the authentication ticket. Upon receiving the authentication ticket from the client the hash can be recomputed and compared against the hash sent by the client. If these two hashes match up, the authentication ticket data has not been modified by any client or in transit; if they do not, something's gone awry and the authentication ticket is considered invalid. This MAC protects both against a nefarious user modifying the cookie or that user "baking" their own cookie.
You can customize the level of protection for the authentication ticket. The default is to apply both encryption
and validation, but you can use neither of these techniques (dangerous!), just encryption, or just validation. Additionally,
you can customize what encryption algorithm is used. Additionally, if you are hosting in a web farm scenario you'll need
to explicitly specify the secret key used by the web server when encrypting the data and when applying the MAC, because
you'll want all servers in the farm to use the same keys. All of these settings can be configured through the
Conclusion Happy Programming!
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
![]() |
![]() |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|