Authentication and AJAX

Getting Credentials and Sharing Tokens in AJAX Is Much the Same as in Classic ASP.NET

Dino Esposito

October 30, 2009

10 Min Read
ITPro Today logo

CoreCoder

LANGUAGES: C#

ASP.NETVERSIONS: 3.5

 

Authentication and AJAX

Getting Credentials and Sharing Tokens in AJAX Is Muchthe Same as in Classic ASP.NET

 

By Dino Esposito

 

Because of the statelessness of the HTTP protocol, Webapplications have a lot to gain from server-side services that make up for theextreme simplicity of the protocol. On the other hand, the HTTP protocol wasdesigned for an idea of the Web quite different from the one we have today.Such a simple protocol was just fine for sharing HTML-based and hyperlinkeddocuments; it is less than ideal when we actually use HTML as an applicationdelivery format and claim for security, state maintenance, and caching. At theend of the day, though, HTTP is still there and it forms the foundation ofASP.NET and AJAX.

 

To empower Web applications, virtually all server-sideruntime environments build an abstraction layer and provide additional servicesto applications, such as session state, caching, user profiling, and,especially, authentication and role management.

 

In ASP.NET, the vast majority of these applicationservices are incorporated in the runtime pipeline and use the HTTP moduleinfrastructure. Services intercept pipeline events and kick in whenappropriate. The page developer isn t involved in the services activity andpassively deals with the results of the activity itself. What does it mean? Forexample, if a profiling service is in place, the page developer will findprofile information for the current user ready to use. The same goes for therole management service. But what about authentication, instead?

 

Authentication is a key feature in ASP.NET. It ensuresthat only recognized users are granted access to a given resource be it apage, a folder, or a simple image. Authentication is implemented through anHTTP module that intercepts any request to a protected resource and directs theuser to a log-in page first. Are authentication and other services compatiblewith ASP.NET AJAX?

 

How Authentication Works in ASP.NET

In the configuration file in classic ASP.NET, you declarewhich resources in which folder are off-limits for the anonymous user. At thatpoint, the runtime pipeline automatically redirects the anonymous user to alog-in page, where the user is prompted for credentials. Next, if the user issuccessfully authenticated, an authentication token is generated as a cookieand appended to the response. Finally, the user is redirected to the originallyrequested page and passes any further check because of the attached token.Forms authentication is the ASP.NET built-in infrastructure that implements thelog-in pattern. Forms authentication requires an additional log-in page and twoHTTP redirect commands. Is it possible to save one redirect and authenticatethe user from within an HTML page through an AJAX call?

 

An AJAX Infrastructure for Authentication

For ASP.NET AJAX clients, the infrastructure forauthentication consists of two key components: a client-side JavaScript classand a system-provided HTTP handler. The same model is in place for other systemservices, such as role management and user profiles.

 

The JavaScript class supplies one method to send any user scredentials to a server-side endpoint. The HTTP handler internally invokes asystem-provided scriptable Web service. As a result, you receive a Booleananswer that indicates whether the user has been authenticated or not. The Webservice uses the server-side ASP.NET authentication and membership API tovalidate the user information. When you use a JavaScript proxy to command aremote authentication service, you check your users more quickly because youcan incorporate a log-in form into any pages in the site that users visitregularly. The authentication essentially consists of a request, and doesn tforce a redirect to a specialized log-in page.

 

From JavaScript, you invoke a proxy class implemented as asingleton. The original JavaScript class is instantiated in the Microsoft AJAX clientlibrary and is exposed as an object (as named here):

 

var proxy = Sys.Services.AuthenticationService;

 

The methods offered by the authentication JavaScript proxyclass for ASP.NET AJAX are listed in Figure 1. Figure 2, instead, details theproperties defined on the object. The underlying JavaScript class is a regularJavaScript proxy class nearly identical to any other JavaScript proxy classthat the ScriptManager control generates for referenced Web and WCF services.The only difference is that such proxy classes for authentication, rolemanagement, and profile services are natively part of the Microsoft clientlibrary and downloaded as part of the MicrosoftAjax.js file.

 

Method

Description

login

Verifies credentials and issues an authentication ticket if the credentials are good.

logout

Clears the authentication ticket.

Figure 1: Methodsof the Sys.Services.AuthenticationService object.

 

Property

Description

isLoggedIn

Boolean read-only property; indicates whether the current user is logged in.

path

Gets and sets the URL to reach the authentication Web service.

timeout

Gets and sets the timeout for the user authentication process.

Figure 2: Propertiesof the Sys.Services.AuthenticationService object.

 

The back-end of the authentication service is implementedin the AuthenticationWebService class, marked as sealed and internal. The classfeatures a script service, as illustrated here:

 

[ScriptService]

class AuthenticationService

{

   // Methods

   publicAuthenticationService();

    [WebMethod]

   public boolIsLoggedIn();

    [WebMethod]

   public boolLogin(string userName, string password,

                      bool createPersistentCookie);

    [WebMethod]

   public void Logout();

}

 

Let s focus on the login method. The first two argumentsset the credentials of the user. When you authenticate a user through Formsauthentication, a cookie is created and attached to the response. This cookieis referred to as the authentication cookie and its name defaults to .ASPXAUTH.The final Boolean argument indicates whether a persistent cookie is required.If so, authenticated credentials will be in a persistent cookie saved acrossbrowser sessions.

 

What about the expiration of the authentication cookie?The cookie is simply given the expiration that you specify in the configurationfile. So to set the timeout that is appropriate for your site, you simply setthe timeout attribute in the section of the application sweb.config file to the desired number of minutes. You should note that theauthentication service sets the cookie using the SetAuthCookie method on theFormsAuthentication class. This means that most settings defined in the section of the configuration file are taken into proper account while creatingthe authentication ticket.

 

The Role of Membership Providers

Where would you specify the logic to check credentials?The AJAX authentication service takes advantage of the currently registeredASP.NET membership provider. The default membership provider checks usernameand password against the content of the users table in the aspnetdb.mdf file.However, both the database schema and the logic applied are a detail you canchange at will.

 

If you want to apply an application-specific piece oflogic or reuse an existing database of users, all you have to do is create acustom membership provider. Starting with ASP.NET 2.0, forms authentication isbuilt atop a provider-based, extensible model that lets you easily change theunderlying machinery, such as validation code and users management, whileleaving the front-end API intact. Based on this model, you can easily adaptyour existing code to connect to the authentication machinery of ASP.NET, alsofrom an AJAX client.

 

A custom membership provider takes the form as shown in Figure3. It is essentially a class that inherits from MembershipProvider and overridesa few members. The key member to override is ValidateUser. This method takes ausername and password and returns a Boolean answer. It s within this memberthat you should place your custom logic for managing a user s credentials.

 

public class CustomMembershipProvider : MembershipProvider

{

   publicCustomMembershipProvider()

   {

   }

   public override boolValidateUser(string username, string password)

   {

       returnAuthenticateUser(username, password);

   }

   private bool AuthenticateUser(stringusername, string password)

   {

       // Yourauthentication logic here

   }

   // Override all otherabstract methods in MembershipProvider

   :

}

Figure 3: Skeletonfor a custom membership provider.

 

Note also that MembershipProvider is an abstract classwith a long list of members to override in any derived class. The complete listis shown in Figure 4.

 

public abstract class MembershipProvider : ProviderBase

{

 public abstract boolChangePassword(

     string username,string oldPassword, string newPassword);

 public abstract boolChangePasswordQuestionAndAnswer(

     string username,string password, string newPasswordQuestion,

      string newPasswordAnswer);

 public abstractMembershipUser CreateUser(

     string username,string password, string email, string passwordQuestion,

     stringpasswordAnswer, bool isApproved, object providerUserKey,

     outMembershipCreateStatus status);

 public abstract boolDeleteUser(

     string username, booldeleteAllRelatedData);

   public abstract MembershipUserCollectionFindUsersByEmail(

     string emailToMatch,int pageIndex, int pageSize, out int totalRecords);

 public abstractMembershipUserCollection FindUsersByName(

     stringusernameToMatch, int pageIndex, int pageSize, out int totalRecords);

 public abstractMembershipUserCollection GetAllUsers(

     int pageIndex, intpageSize, out int totalRecords);

 public abstract intGetNumberOfUsersOnline(

     );

 public abstract stringGetPassword(

     string username, stringanswer);

 public abstractMembershipUser GetUser(

     objectproviderUserKey, bool userIsOnline);

 public abstractMembershipUser GetUser(

     string username, booluserIsOnline);

 public abstract stringGetUserNameByEmail(

     string email);

 public abstract stringResetPassword(

     string username,string answer);

 public abstract boolUnlockUser(

     string userName);

 public abstract voidUpdateUser(

     MembershipUser user);

 public abstract boolValidateUser(

     string username,string password);

 // Properties

 public abstract stringApplicationName { get; set; }

 public abstract boolEnablePasswordReset { get; }

 public abstract boolEnablePasswordRetrieval { get; }

 public abstract intMaxInvalidPasswordAttempts { get; }

 public abstract intMinRequiredNonAlphanumericCharacters { get; }

 public abstract intMinRequiredPasswordLength { get; }

 public abstract intPasswordAttemptWindow { get; }

 public abstractMembershipPasswordFormat PasswordFormat { get; }

 public abstract stringPasswordStrengthRegularExpression { get; }

 public abstract boolRequiresQuestionAndAnswer { get; }

 public abstract boolRequiresUniqueEmail { get; }

}

Figure 4: Definitionof the MembershipProvider class.

 

You are not required to give an effective implementationto each member, but at the very minimum you should throw an exception, as shownhere:

 

public override bool ChangePassword(string username,

   string oldPassword, string newPassword)

{

     throw newNotSupportedException();

}

 

For ASP.NET AJAX, though, there s a quicker way out youmight want to consider. In the System.Web.ClientServices.Providers namespaceyou ll find the ClientFormsAuthenticationMembershipProvider class. This classis essentially an implementation of MembershipProvider that ASP.NET AJAX usesto perform default validation. At the end of the day, this class is arelatively thin wrapper around MembershipProvider that overrides ValidateUserand throws for any other method. You might seriously consider deriving yourcustom provider class from this instead of MembershipProvider.

 

Finally, to register the new membership provider, tweakthe web.config file as shown here:

 

  

              type="YourNamespace.CustomMembershipProvider" />      Add the preceding code to the web.config file under the node and you re done.  Performing Authentication Using ASP.NET AJAX authentication requires a bunch of HTMLinput tags to collect username, password, and the optional checkbox for apersistent cookie. You also need a JavaScript button bound to the followingcode:     var username =$get("Login1_UserName");     var password =$get("Login1_Password");    function Login1_Click()   {       Sys.Services.AuthenticationService.login(           username.value,password.value, false,            null, null,onLoginCompleted);        return false;    }    :   The authentication occurs asynchronously; when all is done,the callback (in this case, onLoginCompleted) is invoked to give you a chanceto update the user interface.   What about the log-out process? To give users a chance tolog out directly from the client, you must add another button to your clientuser interface and bind it to the following JavaScript code:  function Logout1_Click(){ Sys.Services.AuthenticationService.logout(   onLogoutCompleted);  return false; }   The function originates a redirect and a full page reload.The final response doesn t include any more than the authentication cookie.  Brief Notes on AJAX Authentication ASP.NET AJAX authentication needs to be explicitly enabledthrough a setting in the configuration file:                             In ASP.NET, forms authentication always sends credentialsas clear text. This is nothing new, but a reminder is still useful. For anumber of security-related reasons, it is recommended that log-in forms beplaced in pages you reach through HTTPS. Clear text is not related to AJAX, butusing AJAX for authentication certainly makes it easier for developers to placelog-in forms everywhere.   Another point to keep in mind is that the AJAXauthentication service doesn t work with applications that use a cookielessauthentication scheme.  Conclusion Forms authentication is the mechanism in ASP.NETapplications that allows you to show a log-in page in front of users when theyattempt to access a protected resource. In classic ASP.NET,forms authentication is based on a couple of HTTP redirects. In an ASP.NETAJAX scenario, you can use some JavaScript code to make at least the log-inprocess happen in a smoother way.  Dino Esposito is anarchitect at IDesign and specializes mainly in ASP.NET, AJAX, and RIAsolutions. Dino is the author of ProgrammingASP.NET 3.5 Core Reference (Microsoft Press, 2008). He also wrote Introducing ASP.NET AJAX, also for MicrosoftPress. Late-breaking news is available at http://weblogs.asp.net/despos.      

Sign up for the ITPro Today newsletter
Stay on top of the IT universe with commentary, news analysis, how-to's, and tips delivered to your inbox daily.

You May Also Like