Client Application Services - Part 2
page 4 of 10
by Bilal Haidar
Feedback
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days): 44049/ 76

Authentication

Once the client application services are enabled, you can configure what type of authentication to use. For the sake of this article, Forms authentication will be used. Once the radio button Use Forms Authentication is selected, you should provide the remote authentication service location. In this case it is the URL for the ASP.NET website host application that was created in a previous section of this article. When it is time to access the remote authentication service, the Client Application Services framework adds the Authenticate_JSON_AppService.axd to the configured URL. This is the URL for the HttpHandler that will access the configured Membership provider set by the ASP.NET website host application.

The next entry to set is the Credentials provider. As mentioned in part 1 of this article, this should point to the Login form that will be used to gather credentials from the user to authenticate against the remote authentication service. As we will see soon, the Login form will implement the IClientFormsAuthenticationCredentialsProvider interface and provide code for the GetCredentials method. This method will be called when you issue a call to the Membership.ValidateUser method later in the application.

Finally, you should set the URL for the Roles service. The same URL will be used here and again, the Client Application Service framework will append to the URL the Role_JSON_AppService.axd HttpHandler path that will be used to access the remote Roles service.

Now that the Client Application Service is enabled, it is time to create the Login form. We do this by adding a new Windows Form called Login.cs. This form, as mentioned before, should implement the IClientFormsAuthenticationCredentialsProvider interface and provide a method called GetCredentials that will return an instance of ClientFormsAuthenticationCredentials object filled with the credentials entered by the user. The implementation of the form is quiet simple and is shown below.

Listing 3

namespace ClientApplication
{
  public partial class Login: Form,
    IClientFormsAuthenticationCredentialsProvider
  {
    public Login()
    {
      InitializeComponent();
    }
 
    #region IClientFormsAuthenticationCredentialsProvider Members
    public ClientFormsAuthenticationCredentials GetCredentials()
    {
      if (this.ShowDialog() == DialogResult.OK)
      {
        return new ClientFormsAuthenticationCredentials(this.txtUsername.Text,
          this.txtPassword.Text, false);
      }
      else
      {
        return null;
      }
    }
    #endregion
  }
}

You can see how simple it is with the implementation of the GetCredentials method. It shows the Login form and waits for the OK button to be clicked, and then it returns an instance of the ClientFormsAuthenticationCredentials containing the credentials entered by the user.

After developing the Login form, we will create the main applications’ form. In the Form_Load event of this form, we will issue a call to validate the user as shown below.

Listing 4

private void Form1_Load(object sender, EventArgs e)
{
  // Validate the user
  if (!ValidateUser())
    return ;
 
  // Fill user information
  DisplayUserInfo();
}
 
private bool ValidateUser()
{
  bool isAuthenticated = false;
  try
  {
    isAuthenticated = Membership.ValidateUser(string.Empty, string.Empty);
  }
  catch (System.Net.WebException ex)
  {
    // a WebException is raised when the authentication service
    // cannot be reached
    if (DialogResult.OK == MessageBox.Show(
      "Unable to access the authentication service""Not logged in",
      MessageBoxButtons.OK, MessageBoxIcon.Error))
      Application.Restart();
  }
 
  if (!isAuthenticated)
  {
    MessageBox.Show("Unable to authenticate credentials""Not logged in",
      MessageBoxButtons.OK, MessageBoxIcon.Error);
    Application.Exit();
  }
 
  return isAuthenticated;
}

In the Form_Load event there is a call to ValidateUser method which calls the Membership.ValidateUser method. Calling this method with empty string is a must so that the credentials login form pops up.

If the authentication service is unavailable, then a System.Net.WebException is thrown. If ValidateUser method returns true, the current user is now authenticated and an authentication cookie is now created for the user on the local hard disk.

In addition, there is a call for the method DisplayUserInfo. This method shall bind a label on the main form to some information about the user, mainly a welcome message, and display the authentication type.

Listing 5

private void DisplayUserInfo()
{
  // Get the ClientFormsIdentity
  ClientFormsIdentity user = (ClientFormsIdentity)
    System.Threading.Thread.CurrentPrincipal.Identity;
  StringBuilder sb = new StringBuilder();
  sb.AppendFormat("Welcome {0} !! \r\n\r\n" + "Authentication Type: {1} \r\n",
    user.Name, user.AuthenticationType);
  this.label1.Text = sb.ToString();
}

Notice how we are retrieving an instance of the ClientFormsIdentity by casting the Identity property on the System.threading.Thread.CurrentPrincipal object.


View Entire Article

User Comments

Title: Continuing last comment   
Name: Krishna Vedula
Date: 2010-04-04 7:22:11 PM
Comment:
Hello Bilal

Looks like there is a limit on the length of the comment. So, here are my details

Krishna Vedula
krishna@ntc-us.com
Title: How to pass the user context back to server   
Name: Krishna J Vedul
Date: 2010-04-04 7:21:12 PM
Comment:
Hello Bilal,

Great Series of articles going in depth in to each of the security topics. I found this very helpful. This helped me get a general direction for the project I am working on currently. However, I have come across a road-block in all articles related to Client Application Services across many sites and was not able to get much help in that regard.

What I am trying exactly is to have the same Authentication framework for my Web front-end as well as the Web interface. With Client Application Services, I am able to get that as explained by you clearly. I also get the roles of the user, so I control what to show and what not to show. Great so far.

I am going to the next level, where my Desktop application is connecting back to the same server (that server the authentication as well as web-content) to get some data. Here I have created some facades (aspx) to parse the request data and send the response as XML. I am able to use the same business objects with some custom aspx files for xml transformation. But, I am getting an error in the business layer if I put any security role restrictions.

How do I pass the Thread.CurrentPrincipal.Identity which has all the roles back to through the web request so that the security framework on the server would not throw any execptions.

a) Code I am using to create a request on the client is

HttpWebRequest req = (HttpWebRequest)WebRequest.Create(@"http://localhost:55555/AppServices/GetAdminData.aspx");
req.Method = WebRequestMethods.Http.Post;

b) Security Permissions on the server are like


[PrincipalPermissionAttribute(SecurityAction.Demand, Role="admin")]
public void ProcessRequest()
{

If I could pass all the cookies that come from user authentication back to server as part of the request, then I woudl get over the problem. But with Membership.ValidateUser I do not get any cookies. Then how do I pass them?

The SaveUserSettings seems to send the user
Title: Good Article   
Name: Adron
Date: 2008-10-20 12:07:25 AM
Comment:
Good write up. I'm working through multiple scenarios right now with this, so it is interesting to read and helpful.

Thx.






Community Advice: ASP | SQL | XML | Regular Expressions | Windows


©Copyright 1998-2024 ASPAlliance.com  |  Page Processed at 2024-04-26 11:59:24 AM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search