web analytics

Understanding ASP.NET Authentication

Options
@2016-12-13 23:38:13

Forms Authentication Credentials

Forms authentication credentials that are used to validate users at logon can be stored in an external data source or in the application configuration file.

Storing Users in the Application Configuration File

When using forms authentication, you can validate users from user/password pairs in the credentials section of the Web site's configuration file. You can use the Authenticate method to compare the credentials collected from the user to the list of user/password pairs in the credentials section to determine whether access should be granted. In the following example, users Kim and John can log on if they provide the correct password.

<credentials passwordFormat="SHA1" >
    <user name="Kim"
          password="07B7F3EE06F278DB966BE960E7CBBD103DF30CA6"/>
    <user name="John" 
          password="BA56E5E0366D003E98EA1C7F04ABF8FCB3753889"/>
</credentials>

The credential pairs in the example are encrypted using the Secure Hash Algorithm-1 (SHA1) password-hashing format. The PasswordFormat attribute is required. Values for this property are listed in the following table.

 

Value

Description

Clear

Passwords are stored in clear text. The user password is compared directly to this value without further transformation.

MD5

Passwords are stored using a Message Digest 5 (MD5) hash digest. To validate credentials, the user password is hashed using the MD5 algorithm and compared to the stored value. The clear-text password is never stored or compared when using this value. This algorithm produces better performance than SHA1.

SHA1

Passwords are stored using the SHA1 hash digest. To validate credentials, the user password is hashed using the SHA1 algorithm and compared to the stored value. The clear-text password is never stored. Use this algorithm for improved security over the MD5 algorithm.

The .NET Framework includes classes and methods that make it easy for you to create hashed values programmatically for persistent storage. One class that can be helpful for programming this task is the FormsAuthentication class. Its HashPasswordForStoringInConfigFile method can do the hashing. For more precise control, you can use the System.Security.Cryptography classes as well.

Hashed passwords stored in a text file cannot be used to regenerate the original password, but they are potentially vulnerable to a dictionary attack. In this type of attack, the attacker, after gaining access to the password file, attempts to guess passwords by using software to iteratively hash all words in a large dictionary and compare the generated hashes to the stored hash. If you store hashed passwords in any way, you should require your users to choose passwords that are not common words and that contain some numbers and non-alphanumeric characters to help prevent dictionary attacks. Additionally, you can make credentials management easier by storing them using ASP.NET membership.

Managing Users by Using Membership

ASP.NET membership enables you to validate and manage user information for your Web application. It provides functionality for validating user credentials, creating and modifying membership users, and managing user settings such as passwords and e-mail addresses. ASP.NET membership is primarily intended for use with ASP.NET forms authentication, but can be used anywhere within an ASP.NET application.

ASP.NET membership enables you to manage user authentication for your application while keeping the user information in the data source of your choice. Because ASP.NET membership uses providers to the membership data source, it does not require extensive code to read and write membership information.

ASP.NET membership consists primarily of built-in membership providers, which communicate with the data source, and the static Membership class that exposes the functionality of the membership providers. You call the Membership class from your ASP.NET code to perform user validation and management.

@2017-01-26 13:58:32

Forms authentication lets you authenticate users by using your own code and then maintain an authentication token in a cookie or in the page URL. Forms authentication participates in the ASP.NET page life cycle through the FormsAuthenticationModule class. You can access forms authentication information and capabilities through the FormsAuthentication class.

To use forms authentication, you create a login page that collects credentials from the user and that includes code to authenticate the credentials. Typically you configure the application to redirect requests to the login page when users try to access a protected resource, such as a page that requires authentication. If the user's credentials are valid, you can call methods of the FormsAuthentication class to redirect the request back to the originally requested resource with an appropriate authentication ticket (cookie). If you do not want the redirection, you can just get the forms authentication cookie or set it. On subsequent requests, the user's browser passes the authentication cookie with the request, which then bypasses the login page.

FormsAuthenticationModule

ASP.NET defines a set of HTTP modules in the machine-level Web.config file. These include a number of authentication modules as shown here:

<httpModules>
  ...
  <add name="WindowsAuthentication"
       type="System.Web.Security.WindowsAuthenticationModule" />
  <add name="FormsAuthentication" 
       type="System.Web.Security.FormsAuthenticationModule" />
  <add name="PassportAuthentication" 
       type="System.Web.Security.PassportAuthenticationModule" />
  ...
</httpModules>

Only one authentication module is used for each request. The authentication module that is used depends on which authentication mode has been specified by the authentication element, usually in the Web.config file in the application's virtual directory.

The FormsAuthenticationModule class is activated when the following element is in the Web.config file.

<authentication mode="Forms" />

The FormsAuthenticationModule class constructs a GenericPrincipal object and stores it in the HTTP context. The GenericPrincipal object holds a reference to a FormsIdentity instance that represents the currently authenticated user. You should allow forms authentication to manage these tasks for you. If your applications have specific requirements, such as setting the User property to a custom class that implements the IPrincipal interface, your application should handle the PostAuthenticate event. The PostAuthenticate event occurs after the FormsAuthenticationModule has verified the forms authentication cookie and created the GenericPrincipal and FormsIdentity objects. Within this code, you can construct a custom IPrincipal object that wraps the FormsIdentity object, and then store it in the HttpContext.User property.

Note   If you do this, you will also need to set the IPrincipal reference on the Thread.CurrentPrincipal property to ensure that the HttpContext object and the thread point to the same authentication information.

Forms Authentication Cookies

The FormsAuthentication class creates the authentication cookie automatically when the FormsAuthentication.SetAuthCookie or FormsAuthentication.RedirectFromLoginPage methods are called.

The following properties are included in a typical forms authentication cookie:

  • Name. This property specifies the name of the cookie.
  • Value. This property specifies value of the cookie.

In a typical forms authentication cookie, the value contains a string representation of the encrypted and signed FormsAuthenticationTicket object. The cookie contains the following properties:

  • Expires. This property specifies the expiration date and time for the cookie. Forms authentication only sets this value if your code indicates that a persistent forms-authentication cookie should be issued.
  • Domain. This property specifies the domain with which the cookie is associated. The default value is null.
    • HasKeys. This property indicates whether the cookie has subkeys.
  • HttpOnly. This property specifies whether the cookie can be accessed by client script. In ASP.NET, this value is always set to true. Internet Explorer supports this cookie attribute, which prevents client-side script from accessing the cookie from the document.cookie property. If an attempt is made to access the cookie from client-side script, an empty string is returned. The cookie is still sent to the server whenever the user browses to a Web site in the current domain.
    Note   Web browsers that do not support the HttpOnly cookie attribute either ignore the cookie or ignore the attribute, which means that the session is still subject to cross-site scripting attacks.
  • Path. This property specifies the virtual path for the cookie. The default value is "/", indicating root directory.
  • Secure. This property specifies whether the cookie should only be transmitted over an HTTPS connection. The Secure property should be set to true so that the cookie is protected by SSL encryption.
  • Version. This property specifies the version number of the cookie.

Creating the Forms Authentication Cookie

The forms authentication cookie is created by the FormsAuthentication class as follows. Once the user is validated, the FormsAuthentication class internally creates a FormsAuthenticationTicket object by specifying the cookie name; the version of the cookie; the directory path; the issue date of the cookie; the expiration date of the cookie; whether the cookie should be persisted; and, optionally, user-defined data.

FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1,
        "userName",
        DateTime.Now,
        DateTime.Now.AddMinutes(30), // value of time out property
        false, // Value of IsPersistent property
        String.Empty,
        FormsAuthentication.FormsCookiePath);
  

Next, forms authentication uses the Encrypt method for encrypting and signing the forms authentication ticket, if the protection attribute of the forms element is set to All or Encryption.

string encryptedTicket = FormsAuthentication.Encrypt(ticket);
  

The following text shows the process used when the protection attribute is set to All:

  • Create a serialized forms authentication ticket. A byte array representation of the ticket is created.
  • Sign the forms authentication ticket. The message authentication code (MAC) value for the byte array is computed by using the algorithm and key specified by the validation and validationKey attributes of the machineKey element. By default, the SHA1 algorithm is used.
  • Encrypt forms authentication ticket. The second byte array that has been created is encrypted by using the Encrypt method of the FormsAuthentication class. The Encrypt method internally uses the algorithm and key specified by the decryption and decryptionKey attributes on the machineKey element. ASP.NET version 1.1 uses the 3DES algorithm by default. ASP.NET version 2.0 uses the Rinjdael (AES) algorithm by default.
  • Create HTTP cookie or query string as appropriate. The encrypted authentication ticket is then added to an HttpCookie object or query string if forms authentication is configured for cookieless authentication. The cookie object is created using the following code:
    HttpCookie authCookie = new HttpCookie(
                                FormsAuthentication.FormsCookieName, 
                                encryptedTicket);
      
  • Set forms authentication cookie as secure. If the forms authentication ticket is configured to use SSL, the HttpCookie. Secure property is set to true. This instructs browsers to only send the cookie over HTTPS connections.
    authCookie.Secure = true;
      
  • Set the HttpOnly bit. In ASP.NET, this bit is always set.
  • Set appropriate cookie attributes. If needed, set the path, domain and expires attributes of the cookie.
  • Add the cookie to the cookie collection. The authentication cookie is added to the cookie collection to be returned to the client browser.
    Response.Cookies.Add(authCookie);
      

Each time a subsequent request is received after authentication, the FormsAuthenticationModule class retrieves the authentication ticket from the authentication cookie, decrypts it, computes the hash value, and compares the MAC value to help ensure that the cookie has not been tampered with. Finally, the expiration time contained inside of the forms authentication ticket is verified.

Note   ASP.NET does not depend on the expiration date of the cookie because this date could be easily forged.
@2017-03-21 13:59:13

How to create and handle GenericPrincipal and FormsIdentity objects when using Forms authentication

Applications that use Forms authentication will often want to use the GenericPrincipal class (in conjunction with the FormsIdentity class), to create a non-Windows specific authorization scheme, independent of a Windows domain.

For example, an application may:

  • Use Forms authentication to obtain user credentials (user name and password).
  • Validate the supplied credentials against a data store; for example, a database or Microsoft® Active Directory® directory service.
  • Create GenericPrincipal and FormsIdentity objects based on values retrieved from the data store. These may include a user's role membership details.
  • Use these objects to make authorization decisions.

This How To describes how to create a Forms-based Web application that authenticates users and creates a custom Forms authentication ticket that contains user and role information. It also shows you how to map this information into GenericPrincipal and FormsIdentity objects and associate the new objects with the HTTP Web request context (HttpContext), allowing them to be used for authorization logic within your application.

Step 1. Create a Web Application with a Logon Page

This procedure creates a new ASP.NET Web application. The application will contain two pages; a default page that only authenticated users are allowed to access, and a logon page used to collect user credentials.

To create a Web application with a logon page

  1. Start Visual Studio .NET and create a new C# ASP.NET Web Application called GenericPrincipalApp.
  2. Rename WebForm1.aspx to Logon.aspx.
  3. Add the following controls to Logon.aspx to create a logon form.

    Table 1: Logon.aspx controls

    Control Type Text ID
    Label User Name: -
    Label Password -
    Text Box - txtUserName
    Text Box - txtPassword
    Button Logon btnLogon
  4. Set the TextMode property of the password Text Box control to Password.
  5. In Solution Explorer, right-click GenericPrincipalApp, point to Add, and then click Add Web Form.
  6. Enter default.aspx as the new form's name, and then click Open.

Step 2. Configure the Web Application for Forms Authentication

To edit the application's Web.config file to configure the application for Forms authentication

  1. Use Solution Explorer to open Web.config.
  2. Locate the <authentication> element and change the mode attribute to Forms.
  3. Add the following <forms> element as a child of the <authentication> element and set the loginUrl, name, timeout, and path attributes as follows:
    <authentication mode="Forms">
      <forms loginUrl="logon.aspx" name="AuthCookie" timeout="60"
        path="/">
      </forms>
    </authentication>
    
  4. Adding the following credential element in the <forms> element
    <credentials passwordFormat="SHA1" >
    <!-- pwd: helloworld-->
       <user name="test" password="6ADFB183A4A2C94A2F92DAB5ADE762A47889A5A1"/>
    </credentials>
  5. Add the following <authorization> element beneath the <authentication> element. This allows only authenticated users to access the application. The previously established loginUrl attribute of the <authentication> element redirects unauthenticated requests to the Logon.aspx page.
    <authorization> 
      <deny users="?" />
      <allow users="*" />
    </authorization>
    

Step 3. Generate an Authentication Ticket for Authenticated Users

This procedure writes code to generate an authentication ticket for authenticated users. The authentication ticket is contained within the authentication cookie used by the ASP.NET FormsAuthenticationModule.

The authentication code typically involves looking up the supplied user name and password against either a custom database or against Active Directory. In this demo application, user/password pairs is stored in the credentials section of the Web site's configuration file.

To generate an authentication ticket for authenticated users

  1. Open the Logon.aspx.cs file and the following using statement to the top of the file beneath the existing using statements:
    using System.Web.Security;
    
  2. Add the following private helper method to the WebForm1 class called IsAuthenticated, which is used to validate user names and passwords to authenticate users. This code assumes that all user name and password combinations are valid.
    private bool IsAuthenticated( string username, string password )
    {
      // Lookup code omitted for clarity
      // This code would typically validate the user name and password
      // combination against a SQL database or Active Directory
      // Simulate an authenticated user
      return FormsAuthentication.Authenticate(username, password);
    }
    
  3. Add the following private helper method called GetRoles, which is used to obtain the set of roles that the user belongs to.
    private string GetRoles( string username)
    {
      // Lookup code omitted for clarity
      // This code would typically look up the role list from a database
      // table.
      // If the user was being authenticated against Active Directory,
      // the Security groups and/or distribution lists that the user
      // belongs to may be used instead
    
      // This GetRoles method returns a pipe delimited string containing
      // roles rather than returning an array, because the string format
      // is convenient for storing in the authentication ticket /
      // cookie, as user data
      return "Senior Manager|Manager|Employee";
    }
    
  4. Display the Logon.aspx form in Designer mode and double-click the Logon button to create a click event handler.
  5. Add a call to the IsAuthenticated method, supplying the user name and password captured through the logon form. Assign the return value to a variable of type bool, which indicates whether or not the user is authenticated.
    bool isAuthenticated = IsAuthenticated( txtUserName.Text,
                                            txtPassword.Text );
    
  6. If the user is authenticated, add a call to the GetRoles method to obtain the user's role list.
    if (isAuthenticated == true )
    {
      string roles = GetRoles( txtUserName.Text);
    
  7. Create a new forms authentication ticket that contains the user name, an expiration time, and the list of roles that the user belongs to. Note that the user data property of the authentication ticket is used to store the user's role list. Also note that the following code creates a non-persistent ticket, although whether or not the ticket / cookie is persistent is dependent upon your application scenario. Persisting authentication cookies is not recommended because they are vulnerable to attacks.
      // Create the authentication ticket
      FormsAuthenticationTicket authTicket = new
           FormsAuthenticationTicket(1,                          // version
                                     txtUserName.Text,           // user name
                                     DateTime.Now,               // creation
                                     DateTime.Now.AddMinutes(60),// Expiration
                                     false,                      // Persistent
                                     roles );                    // User data
    
  8. Add code to create an encrypted string representation of the ticket and store it as data within an HttpCookie object.
      // Now encrypt the ticket.
      string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
      // Create a cookie and add the encrypted ticket to the
      // cookie as data.
      HttpCookie authCookie = 
                   new HttpCookie(FormsAuthentication.FormsCookieName,
                                  encryptedTicket);
    
  9. Add the cookie to the cookies collection returned to the user's browser.
      // Add the cookie to the outgoing cookies collection.
      Response.Cookies.Add(authCookie);
    
  10. Redirect the user to the originally requested page
      // Redirect the user to the originally requested page
      Response.Redirect( FormsAuthentication.GetRedirectUrl(
                                                    txtUserName.Text,
                                                    false ));
    }
    

Step 4. Construct GenericPrincipal and FormsIdentity Objects

This procedure implements an application authentication event handler and constructs GenericPrincipal and FormsIdentity objects based on information contained within the authentication ticket.

To construct GenericPrincipal and FormsIdentity objects

  1. From Solution Explorer, open global.asax.
  2. Switch to code view and add the following using statements to the top of the file:
    using System.Web.Security;
    using System.Security.Principal;
    
  3. Locate the Application_AuthenticateRequest event handler and add the following code to obtain the forms authentication cookie from the cookie collection passed with the request.
    // Extract the forms authentication cookie
    string cookieName = FormsAuthentication.FormsCookieName;
    HttpCookie authCookie = Context.Request.Cookies[cookieName];
    
    if(null == authCookie)
    {
      // There is no authentication cookie.
      return;
    } 
    
  4. Add the following code to extract and decrypt the authentication ticket from the forms authentication cookie.
    // Extract and decrypt the authentication ticket 
    FormsAuthenticationTicket authTicket = null;
    try
    {
      authTicket = FormsAuthentication.Decrypt(authCookie.Value);
    }
    catch(Exception ex)
    {
      // Log exception details (omitted for simplicity)
      return;
    }
    
    if (null == authTicket)
    {
      // Cookie failed to decrypt.
      return; 
    } 
    
  5. Add the following code to parse out the pipe separate list of role names attached to the ticket when the user was originally authenticated.
    // When the ticket was created, the UserData property was assigned a
    // pipe delimited string of role names.
    string[] roles = authTicket.UserData.Split(new char[]{'|'});
    
  6. Add the following code to create a FormsIdentity object with the user name obtained from the ticket name and a GenericPrincipal object that contains this identity together with the user's role list.
    // Create an Identity object
    FormsIdentity id = new FormsIdentity( authTicket ); 
    
    // This principal will flow throughout the request.
    GenericPrincipal principal = new GenericPrincipal(id, roles);
    
    // Attach the new principal object to the current HttpContext object
    Context.User = principal;
    

Step 5. Test the Application

This procedure adds code to the default.aspx page to display information from the GenericPrincipal object attached to the current HttpContext object, to confirm that the object has been correctly constructed and assigned to the current Web request. You will then build and test the application.

To test the application

  1. In Solution Explorer, double-click default.aspx.
  2. Double-click the default.aspx Web form to display the page load event handler.
  3. Scroll to the top of the file and add the following using statement beneath the existing using statements.
    using System.Security.Principal;
    
  4. Return to the page load event handler and add the following code to display the identity name attached to the GenericPrincipal associated with the current Web request.
    IPrincipal p = HttpContext.Current.User;
    Response.Write( "Authenticated Identity is: " +
                    p.Identity.Name );
    Response.Write( "<p>" );
    
  5. Add the following code to test role membership for the current authenticated identity.
    if ( p.IsInRole("Senior Manager") )
      Response.Write( "User is in Senior Manager role<p>" );
    else
      Response.Write( "User is not in Senior Manager role<p>" );
    
    if ( p.IsInRole("Manager") )
      Response.Write( "User is in Manager role<p>" );
    else
      Response.Write( "User is not in Manager role<p>" );
    
    if ( p.IsInRole("Employee") )
      Response.Write( "User is in Employee role<p>" );
    else
      Response.Write( "User is not in Employee role<p>" );
    
    if ( p.IsInRole("Sales") )
      Response.Write( "User is in Sales role<p>" );
    else
      Response.Write( "User is not in Sales role<p>" );
    
  6. In Solution Explorer, right-click default.aspx, and then click Set As Start Page.
  7. On the Build menu, click Build Solution. Eliminate any build errors.
  8. Press Ctrl+F5 to run the application. Because default.aspx is configured as the start up page, this is the initially requested page.
  9. When you are redirected to the logon page (because you do not initially have an authentication ticket), enter a user name and password (test/helloworld), and then click Logon.
  10. Confirm that you are redirected to default.aspx and that the user identity and the correct role details are displayed. The user should be a member of the Senior Manager, Manager, and Employee role, but not a member of the Sales role.
@2017-03-23 09:30:14

ASP.NET Membership

ASP.NET introduces a membership feature and set of login Web server controls that simplify the implementation of applications that use forms authentication.

Membership provides credential storage and management for application users. It also provides a membership API that simplifies the task of validating user credentials when used with forms authentication. The membership feature is built on top of a provider model. This model allows implementing and configuring different providers pointing to different user stores. ASP.NET includes the following membership providers:

  • Active Directory membership provider. This provider uses either an Active Directory or Active Directory Application Mode (ADAM) user store.
  • SQL Server membership provider. This provider uses a SQL Server user store.

You can also add support for custom user stores. For example, you can add support for other Lightweight Directory Access Protocol (LDAP) directories or other existing corporate identity stores. To do so, create a custom provider that inherits from the MembershipProvider abstract base class.

ASP.NET login controls automatically use membership and forms authentication and encapsulate the logic required to prompt users for credentials, validate users, recover or replace passwords, and so on. In effect, the ASP.NET login controls provide a layer of abstraction over forms authentication and membership, and they replace most, or all of, the work you would normally have to do to use forms authentication.

Comments

You must Sign In to comment on this topic.


© 2024 Digcode.com