in

ASP.NET Weblogs

A Recipe for New Media

AJAX and Authentication and Profile Services

Still working on our company website, today I decided to try out the Authentication and Profile Services that are part of the ASP.NET AJAX Extensions.  Basically (for those who don't know) the Authentication and Profile Services are a set of Javascript classes (Sys.Services.AuthenticationService and Sys.Services.ProfileService respectively) and some built in web services that are part of the extensions, that allow you to log in with actually have to refresh the page or redirect to a new page (and logout as well, but it redirects and/or refreshes the page after it asynchronously logs out) and access ASP.NET Profile properties (both read and write, more on that in a minute).  So basically these services allow you to not have to reload pages to access information and manage your logged in state, which means faster response times and smoother user experiences.

So let's look at how we go about doing this.  I will assume that you have started from an already existing ASP.NET AJAX-enabled website.  (If not, just start Visual Studio 2005 and select ASP.NET AJAX-Enabled Web Site, if you don't see that option, you probably don't have the ASP.NET AJAX Extensions installed, go here to get them).  You will also have to configure your website to use ASP.NET Authentication (I'm not going to cover that here, but you can go here for a good tutorial on Membership, Roles and Profiles (including authentication)).

Ok, let's begin.  The first thing you need to do is turn on the services.  In your web.config you will find a configuration section called <system.web.extensions> (you can actually search for that, including the brackets.) and within that section you will find two lines <authenticationService enabled="true" requireSSL="true|false"/> and <profileService enabled="true" readAccessProperties="" writeAccessProperties="" />.  They are currently commented out.  Uncomment them.  The next thing you need to do is decide if you want to force your site to have to use SSL for the authentication process (to protect the username and password), if you can use SSL then go ahead and put true in requireSSL, otherwise put false.  The next step is decide what properties you want to expose via the profileService.  Let me explain this part in a bit more detail.

This is how my profile is defined:

<profile enabled="true">
      <properties>
        <group name="Address">
          <add name="Street1" type="string"/>
          <add name="Street2" type="string"/>
          <add name="City" type="string"/>
          <add name="Province" type="string"/>
          <add name="Postal" type="string"/>
          <add name="Country" type="string"/>
        </group>
        <group name="Contact">
          <add name="Name" type="string"/>
          <add name="Title" type="string"/>
          <add name="Phone" type="string"/>
          <add name="Cell" type="string"/>
          <add name="Fax" type="string"/>
          <add name="Website" type="string"/>
        </group>
        <add name="CompanyName" type="string"/>
      </properties>
    </profile>

So I decided that I wanted to be able to expose the Contact Name and the Company Name, so I wrote my readAccessProperties attribute like so readAccessProperties="Contact.Name,CompanyName". Notice how I accessed a property group by using dot notation (Contact as you can see above is a property group and Name is a property in the property group).  In code, I would access the property via [Page].Profile.Contact.Name.  If you want to give write access to Profile properties then place their names in the writeAccessProperties attribute.

The next step is setting up authentication in the page.  The first thing I did was put two input boxes on the page and called one username and the other password.  Then I placed a button on the form that when clicked would fire a javascript event called Login.

<table id="LoginBox">
    <tr>
        <td>Username: <input type="text" id="username" /></td>
        <td>Password: <input type="text" id="password" /></td>
        <td><input type="button" value="Log in" onclick="Login()" /></td>
    </tr>
</table>

The next step is writing the login function:

var uid = $get("username").value;var pwd = $get("password").value;
Sys.Services.AuthenticationService.login(uid,pwd,false,null,null,OnLoginCompleted,OnCommunicationFailed, null);

Now we need to write the functions that handle if the login call was successful (not if logging in was successful, that's handled later) or not.

function OnLoginCompleted(isValid,userContext, methodName) {
    if (isValid) {
        LoadProfile(userContext);
        }
    else {
        alert("Login failed.");
    }
}

function OnCommunicationFailed(error, userContext, methodName){    alert("Attempt failed: " + error.get_message());}

Obviously, you can make these functions much more "elegant", but these will do for now.  At this point (apart from the LoadProfile method call), you can log someone in and handle a successful login or a bad username/password.  And if there is a communication failure with the server, it will call OnCommunicationFailed.  Logging someone out is as simple as calling Sys.Services.AuthenticationService.logout(null, null, OnCommunicationFailed, null);  If you want to redirect the user to a new page upon successful logout, then replace the first null with the location path.  If you leave it as null it will refresh the page upon successful logout.

Profile Service

Now we will look at the profile service, which in my example is where the LoadProfile method call from the Authentication example above comes in.  And here it is:

function LoadProfile(){
    Sys.Services.ProfileService.load(null, OnProfileLoadCompleted, OnProfileFailed, null); 
}

It is farily sipmlye call.  What it does is call in the AJAX Extensions embedded web service to retrieve the profile properties that were specified in the web.config file.  How these properties are accessed can be seen in the OnProfileLoadCompleted method:

function OnProfileLoadCompleted(numProperties, userContext, methodName){
    $get("LoginBox").style.display = "none";
    welcomeBox.innerHTML = "Welcome " + Sys.Services.ProfileService.properties.Contact.Name + "<input type='button' value='logout' onclick='LogOut()'>";   
   
__doPostBack('UpdatePanel1', '');
}

As you can see it is very easy to access profile properties as they simply become part of the properties property on the ProfileService object (the second line of the function).  Remember though that only the profile properties you specify in the web.config get exposed.  The first line of the method above hides the login box.  The second line replaces the login box with a welcome message that is personalized with the user's full name.  The last line is interesting though.  Once you are logged in, you want to display content that is specific to being logged in.  How I did that in the website is refresh an AJAX UpdatePanel and that is what this line does.  The Postback functionality of ASP.NET gets "hijacked" by the AJAX Extensions so that if an Async trigger (the UpdatePanel Trigger collection defines these) or an UpdatePanel is the target of the Postback, it stops the regular post back and performs an Async callback and reloads the specified UpdatePanel.

And that is basically my experience with Authentication and Profile Services within the AJAX Extensions.  Simple, but powerful.

Comments

 

minos said:

That's really a great article.

As the code itself it is simple an powerful.

It helped me a lot. Well done!

December 16, 2007 8:11 AM

Leave a Comment

(required)  
(optional)
(required)  
Add