Content
1.Introduction
2.Web service
3.Soap Header
4.Web service Implementation
5.SoapHeader Implementation
6.Build token using Cryptography
7.Invoke Web service in client and pass the user credential
8.Conclusion
Introduction
The purpose this article is to explore the exchange of user credentials using
the soap header between client and webs service with Cryptography.Nowadays web
service is most popular platform independent services.so most of the organization
they would have to all data integration using web services. for example CRM.So
this point most of developer they ask question about how about security strength.SOAP
has solution for that it. When we implement web service you can use the SOAP
Header and explicit you override to exchange the user security token between
client and server.
If you are a beginner for web service , To get more information about the web service
just visit here
1.http://www.w3schools.com/webservices/default.asp
2.http://www.west-wind.com/presentations/dotnetwebservices/DotNetWebServices.asp
Web Services
Web services are application components
- Web services communicate using open protocols
- Web services are self-contained and self-describing
- Web services can be discovered using UDDI
- Web services can be used by other applications
- XML is the basis for Web services
Soap Header
The optional SOAP Header element contains application-specific information (like
authentication, payment, etc) about the SOAP message.If the Header element is
present, it must be the first child element of the Envelope element.
Implementation
Lets start web service implementation to this you need open visual studio , click
File menu then click new website you will get collection project temple window
from that you need select ASP.NET web service (if you are using Visual Studio
2008) and supply website name as "http://localhost/UserCredentialWithSHInWebService"
and click ok button. take a look following figure to clear understanding.

Now we created project next steps we need do two important work first you we need
create SOAP Header class.
Soap header Implementation
Right on the web project then add new class call as "SoapUserAuthenticationHeader"
and click OK button.here you need inherit your SoapUserAuthenticationHeader class
from the SoapHeader, then only you could add attribute to web service method.The
SoapUserAuthenticationHeader class file like followings.
SoapUserAuthenticationHeader.cs
using System;
using System.Xml;
using System.Xml.Serialization;
using System.Web.Services.Protocols;
public class SoapUserAuthenticationHeader : SoapHeader
{
public SoapUserAuthenticationHeader()
{
}
public SoapUserAuthenticationHeader(string username, string token)
{
this.username = username;
this.token = token;
}
string username;
public string Username
{
get { return username; }
set { username = value; }
}
string token;
public string Token
{
get { return token; }
set { token = value; }
}
}
SoapUserAuthenticationHeader class is have two properties first for user name and
second one for user taken(encrypted password).And important note here you should
inherit from SoapHeader class.
Web service Implementation
To this I'm going to take a simple example, if you are have sent valid token to server
then server return success message or else return failed message.
DataServices.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
/// <summary>
/// Summary description for DataServices
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment
the following line.
// [System.Web.Script.Services.ScriptService]
public class DataServices : System.Web.Services.WebService
{
public SoapUserAuthenticationHeader UserCredential;
[WebMethod]
[SoapHeader("UserCredential", Direction = SoapHeaderDirection.In)]
public string Message(string[] data)
{
if (UserCredential != null)
{
if (SecurityManager.IsValidUser(UserCredential))
{
return "You are welcome";
}
}
return "You are token not valid, please try with new token";
}
}
Let's look [SoapHeader("UserCredential", Direction = SoapHeaderDirection.In)] in the above code.Just explicit tell to web
service method you need a soap header and this direction as IN
One more class i were added to web service project to make easy
SecurityManager.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
/// <summary>
/// Summary description for SecurityManager
/// </summary>
public class SecurityManager
{
public static bool IsValidUser(SoapUserAuthenticationHeader usercredential)
{
string encryptedPass = usercredential.Token;
string plianPass = new CustomSecutiry().Decrypt(encryptedPass);
if (usercredential.Username.Equals("test"))
{
if (plianPass.Equals("pass"))
{
return true;
}
}
return false;
}
}
In this class i have a method to valid user name ans token .and look at this line
string plianPass = new CustomSecutiry().Decrypt(encryptedPass);
When user pass password from the client just sent as encrypted token to server.server
need decrypt that token and then check with password value.To this i have a common
class call as "CutomSecutiy" this class have implemented methods to
encrypt and decrypt using Cryptography.
Build token using Cryptography
CutomSecutiy.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
using System.IO;
public class CustomSecutiry
{
public CustomSecutiry()
{
// Default symmetric algorithm
mCryptoService = new RijndaelManaged();
mCryptoService.Mode = CipherMode.CBC;
mAlgorithm = ServiceProviderEnum.Rijndael;
}
public CustomSecutiry(ServiceProviderEnum serviceProvider)
{
// Select symmetric algorithm
switch (serviceProvider)
{
case ServiceProviderEnum.Rijndael:
mCryptoService = new RijndaelManaged();
mAlgorithm = ServiceProviderEnum.Rijndael;
break;
case ServiceProviderEnum.RC2:
mCryptoService = new RC2CryptoServiceProvider();
mAlgorithm = ServiceProviderEnum.RC2;
break;
case ServiceProviderEnum.DES:
mCryptoService = new DESCryptoServiceProvider();
mAlgorithm = ServiceProviderEnum.DES;
break;
case ServiceProviderEnum.TripleDES:
mCryptoService = new TripleDESCryptoServiceProvider();
mAlgorithm = ServiceProviderEnum.TripleDES;
break;
}
mCryptoService.Mode = CipherMode.CBC;
}
public CustomSecutiry(string serviceProviderName)
{
try
{
// Select symmetric algorithm
switch (serviceProviderName.ToLower())
{
case "rijndael":
serviceProviderName = "Rijndael";
mAlgorithm = ServiceProviderEnum.Rijndael;
break;
case "rc2":
serviceProviderName = "RC2";
mAlgorithm = ServiceProviderEnum.RC2;
break;
case "des":
serviceProviderName = "DES";
mAlgorithm = ServiceProviderEnum.DES;
break;
case "tripledes":
serviceProviderName = "TripleDES";
mAlgorithm = ServiceProviderEnum.TripleDES;
break;
}
// Set symmetric algorithm
mCryptoService = (SymmetricAlgorithm)CryptoConfig.CreateFromName(serviceProviderName);
mCryptoService.Mode = CipherMode.CBC;
}
catch
{
throw;
}
}
#region Symmetric cryptography class...
#region Private members...
//private string mKey = "wqdj~yriu!@*k0_^fa7431%p$#=@hd+&";
private string mKey = "wqdj~yriu!@*k0_^fa7431%p$#=@hd+&*&NSGTHYT%$D&*JK(^%GFDE$%TYJ&^%R";
private string mSalt = "*&%^hr^";
private ServiceProviderEnum mAlgorithm;
private SymmetricAlgorithm mCryptoService;
private void SetLegalIV()
{
// Set symmetric algorithm
switch (mAlgorithm)
{
case ServiceProviderEnum.Rijndael:
mCryptoService.IV = new byte[] { 0xf, 0x6f, 0x13, 0x2e, 0x35, 0xc2, 0xcd, 0xf9, 0x5, 0x46, 0x9c, 0xea, 0xa8,
0x4b, 0x73, 0xcc };
break;
default:
mCryptoService.IV = new byte[] { 0xf, 0x6f, 0x13, 0x2e, 0x35, 0xc2, 0xcd, 0xf9 };
break;
}
}
#endregion
#region Public interfaces...
public enum ServiceProviderEnum : int
{
// Supported service providers
Rijndael,
RC2,
DES,
TripleDES
}
public virtual byte[] GetLegalKey()
{
// Adjust key if necessary, and return a valid key
if (mCryptoService.LegalKeySizes.Length > 0)
{
// Key sizes in bits
int keySize = mKey.Length * 8;
int minSize = mCryptoService.LegalKeySizes[0].MinSize;
int maxSize = mCryptoService.LegalKeySizes[0].MaxSize;
int skipSize = mCryptoService.LegalKeySizes[0].SkipSize;
if (keySize > maxSize)
{
// Extract maximum size allowed
mKey = mKey.Substring(0, maxSize / 8);
}
else if (keySize < maxSize)
{
// Set valid size
int validSize = (keySize <= minSize) ? minSize : (keySize - keySize % skipSize) +
skipSize;
if (keySize < validSize)
{
// Pad the key with asterisk to make up the size
mKey = mKey.PadRight(validSize / 8, '*');
}
}
}
PasswordDeriveBytes key = new PasswordDeriveBytes(mKey, ASCIIEncoding.ASCII.GetBytes(mSalt));
return key.GetBytes(mKey.Length);
}
public virtual string Encrypt(string plainText)
{
byte[] plainByte = ASCIIEncoding.ASCII.GetBytes(plainText);
byte[] keyByte = GetLegalKey();
// Set private key
mCryptoService.Key = keyByte;
SetLegalIV();
// Encryptor object
ICryptoTransform cryptoTransform = mCryptoService.CreateEncryptor();
// Memory stream object
MemoryStream ms = new MemoryStream();
// Crpto stream object
CryptoStream cs = new CryptoStream(ms, cryptoTransform, CryptoStreamMode.Write);
// Write encrypted byte to memory stream
cs.Write(plainByte, 0, plainByte.Length);
cs.FlushFinalBlock();
// Get the encrypted byte length
byte[] cryptoByte = ms.ToArray();
// Convert into base 64 to enable result to be used in Xml
return Convert.ToBase64String(cryptoByte, 0, cryptoByte.GetLength(0));
}
public virtual string Decrypt(string cryptoText)
{
// Convert from base 64 string to bytes
byte[] cryptoByte = Convert.FromBase64String(cryptoText);
byte[] keyByte = GetLegalKey();
// Set private key
mCryptoService.Key = keyByte;
SetLegalIV();
// Decryptor object
ICryptoTransform cryptoTransform = mCryptoService.CreateDecryptor();
try
{
// Memory stream object
MemoryStream ms = new MemoryStream(cryptoByte, 0, cryptoByte.Length);
// Crpto stream object
CryptoStream cs = new CryptoStream(ms, cryptoTransform, CryptoStreamMode.Read);
// Get the result from the Crypto stream
StreamReader sr = new StreamReader(cs);
return sr.ReadToEnd();
}
catch
{
return null;
}
}
#endregion
#endregion
}
Look like everything fine in server side , lets create client application to invoke
web service do the testing.To this right click on the project solution and add
a windows application to the solutions give project name as "UserCredentialDemo"
On this project first t you need a button to invoke web service and rename caption
of the button as "Check Me". and then add Custom security class on
this project also. Because of when we send password to server we need encrypt
in the client side.
Then we need add web reference to client application, to this you need right on click
the client project then select Add Web Reference menu.after add web reference
it like look like this.

Let's write few line of code to access web service method.
Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using UserCredentialWithServerDemo.DataServices;
namespace UserCredentialWithServerDemo
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnCheckMe_Click(object sender, EventArgs e)
{
DataServices.DataServices service = new UserCredentialWithServerDemo.DataServices.DataServices();
service.Url = "http://localhost/UserCredentialWithSHInWebService/DataServices.asmx";
SoapUserAuthenticationHeader soapUserAuthenticationHeader=new UserCredentialWithServerDemo.DataServices.SoapUserAuthenticationHeader();
soapUserAuthenticationHeader.Username="test";
soapUserAuthenticationHeader.Token=new CustomSecutiry().Encrypt("pass");
service.SoapUserAuthenticationHeaderValue = soapUserAuthenticationHeader;
string [] data =new string []{"test1","test2"};
string message = service.Message(data);
MessageBox.Show(message, "Server message");
}
}
}
Just take yellow background code line before access web service method , we are setting
user name and token value by SoapUserAuthenticationHeader .
Say if you are not pass user credential through the web service, you will get message
(even you can throw like SoapHeadExeception As well) like you are not authorized
person to access this web service.to test this just remove these lines in client
code and build application and run.
when you click check me button you will get message like followings.

Conclusion
That's all , now we have secured web service server and windows client.I hope this
article will helpful and save time on your development progress.
Download client source code
Download Server source code
Please add comment about this article contents and mistake.
History
2009.05.12:Client source code link updated.
Thank you
RRaveen