Wednesday, February 18, 2009

Passing security credentials to C# 2.0 Web Service using SOAP Header



In a project ,we had a web service that required the client to pass security credentials (user id and password) while calling some of the web methods. First we thought to add two additional parameters (user id and password) to every web method that required authentication. This strategy looked very repetitive and made the method parameter list longer. After exploring for a while we discovered a nice solution of passing credentials through SOAP header. To implement this we need to perform the following steps:

Web Service:

1. Inherit a class from the “System.Web.Services.Protocols.SoapHeader” class that contains the security credential related fields. Put this class into the same file that contains the web service class.

public class SecurityInfo : SoapHeader
{
public string UserID;
public string Password;
}

2. Add a public field into the web service class of the type “SecurityInfo”.

public SecurityInfo SecurityCredentials = new SecurityInfo();

3. Add a “SoapHeader” attribute to the web method that requires access to security credentials passed by the client application. The parameter name of the “SoapHeader” attribute must be same as the public field declared in the above step (“SecurityCredentials” in this case).


[WebMethod(Description = "A method that requires authentication")]
[SoapHeader("SecurityCredentials")]
public void PerformASensitiveTask()
{
//Call the authentication method here with the security credential.

Authenticate(SecurityCredentials);

}

[WebMethod(Description = "Another method that requires
authentication")]
[SoapHeader("SecurityCredentials")]
public void PerformAnotherSensitiveTask()
{
//Call the authentication method here with the security credential.
Authenticate(SecurityCredentials);

}


private void Authenticate(SecurityInfo credentials)
{
// validation logic goes here. An exception is thrown if not validated.
string userId = credentials.UserID;
string password = credentials.Password;
//.....
}


So the final web service code looks like this:


public class TestService : System.Web.Services.WebService
{
public SecurityInfo SecurityCredentials = new SecurityInfo();
public TestService()
{
}

[WebMethod(Description = "A method that requires authentication")]
[SoapHeader("SecurityCredentials")]
public void PerformASensitiveTask()
{
//Call the authentication method here with the security credential.
Authenticate(SecurityCredentials);
}

[WebMethod(Description = "Another method that requires authentication")]
[SoapHeader("SecurityCredentials")]
public void PerformAnotherSensitiveTask()
{
//Call the authentication method here with the security credential.
Authenticate(SecurityCredentials);
}

private void Authenticate(SecurityInfo credentials)
{
// validation logic goes here. An exception is thrown if not validated.
string userId = credentials.UserID;
string password = credentials.Password;
//.....
}

}

public class SecurityInfo : SoapHeader
{
public string UserID;
public string Password;
}


Web Service Consumer (Console App):

After adding a web reference to the web service, Visual Studio automatically adds a “SecurityInfoValue” property to the consumer-side proxy. The security credential class “SecurityInfo” is also exposed to the client application.We just need to instantiate an object of this class,set the credentials and set it into the “SecurityInfoValue” property of the client side proxy class of the web service.We can call multiple web methods after that with the same instance in the current scope.All the web methods will have access to the security credentials.The client code looks like this:



static void Main(string[] args)
{
TestWebService.TestService srvc = new
ServiceTest.TestWebService.TestService();

TestWebService.SecurityInfo sec = new
TestWebService.SecurityInfo();

sec.UserID = "ID";
sec.Password = "Password";
srvc.SecurityInfoValue = sec;

srvc.PerformASensitiveTask();

srvc.PerformAnotherSensitiveTask();

}


I think using “Soap Header” to pass credentials to multiple web methods of a web service is really an elegant solution.

Friday, February 6, 2009

When to apply OOAD concepts and Design Patterns?



I strongly believe that the concepts like OOAD (Object Oriented Analysis and Design) and Design Patterns contribute to make an application well designed and flexible in a very positive way. But over the years I have seen myself and some of my colleagues struggling to decide where to start first in the software design phase when a new project arrives.

Should we list all the memorized design patterns first and search in the requirement list for the scope to apply those?

Should we think of the basic OO concepts like encapsulation, polymorphism or inheritance (“is-a” or “has-a”) and start designing the classes according to those at the first place ?

Often many developers loose the way on their inability to prioritize these processes and thinks too much of theoretical Analysis and Design without concentrating on solving the problem on hand first. I have also faced this problem which is popularly termed as “Analysis Paralysis” in the Software Analysis and Design Books.

I have found an excellent guideline of prioritizing these processes in the book “Head First Object Oriented Analysis and Design” by O’Reilly publication. The guideline suggests that:

1. We should concentrate on solving the problem on hand first with the best possible algorithm and make sure that the software does exactly what the customer expects from it. In a nutshell, if the customer does not recognize the validity of the software, all hard work on Analysis, design, patterns, best practices, latest and greatest technologies gone in vain my friend.

2. After making the software workable, we should apply basic OO principles to make the software flexible by eliminating the duplicate codes and improving a bad design.

3. Finally we should strive for applying proven design patterns so that the software is easy to extend and reuse.


I just wanted to share these principles and priorities with you and believe that remembering the priorities will be helpful to choose the right path while designing and developing software.