Introduction
The following article deals with the implementation of security in Web Services. It briefs about how to make Web Services allow only those requests which have been validated for user name or binary tokens. The following article shows how to create such a service and how to invoke such a service. The platform used for development is Windows XP. Username tokens can be validated against built-in accounts. But for the implementation of Kerberos tokens, the machine needs to belong to a domain and should have the logged-in user listed in the Active Directory. The Kerberos key Distribution Center (KDC) issues tickets on validation.
Using the code
- Make sure you have Microsoft Web Services Enhancements (WSE) 2.0 installed.
- Create a blank solution.
- Add two C# projects to the blank solution.
- ASP.NET Web Service (C#). Name it "service".
- Windows Application (C#). Name it "client".
- Enable WSE on both the projects. This can be done by right clicking on the projects and clicking on WSE 2.0 Settings.
- Make sure that the ASP.NET service has both the WSE enhancements and the SOAP Extensions enabled.
- The client only needs to have WSE enabled.
- There are two parts in the project:
- UserName Token
- Kerberos Token
- Creating the service that will accept a UserName or a Kerberos Token and after validating will execute the WebMethod.
The code
- Namespaces used:
using Microsoft.Web.Services2;
using Microsoft.Web.Services2.Security;
using Microsoft.Web.Services2.Security.Tokens;
- A method
ValidateToken()
is called before actually executing the web method.
[WebMethod]
public long perform(long a,long b)
{
if (ValidateToken())
return a+b;
else
return long.MinValue;
}
- Extracting and verifying the token from the SOAP context:
Copy all the elements from the SOAP context into a collection.
SecurityElementCollection e =
RequestSoapContext.Current.Security.Elements;
Now iterate through the elements to find the message signature.
foreach( ISecurityElement secElement in e )
{
Now find the MessageSignature
if present in the SOAP context.
foreach( ISecurityElement secElement in e )
{
if( secElement is MessageSignature )
{
Now check whether it is a Username token or a Kerberos token and do the needful if validated.
SecurityToken sigTok = msgSig.SigningToken;
if( sigTok is UsernameToken )
{
return sigTok.Principal.IsInRole( @"BUILTIN\Users" );
}
else if( sigTok is KerberosToken )
{
return sigTok.Principal.Identity.IsAuthenticated;
}
- Creating the client.
- Namespaces used are:
using Microsoft.Web.Services2.Security;
using Microsoft.Web.Services2.Security.Tokens;
- Add a web proxy for the service that we just created.
- UserName Token -- the following code creates a UserName Token:
SecurityToken token=null;
switch (option)
{
case "UserName":
{
try
{
UsernameToken unToken=new UsernameToken(textBox1.Text,
textBox2.Text,PasswordOption.SendPlainText);
token=unToken;
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
return;
}
break;
}
- Kerberos Token -- The following code creates a Kerberos Token:
case "Kerberos":
{
try
{
KerberosToken kToken =
new KerberosToken(System.Net.Dns.GetHostName() );
token=kToken;
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
return;
}
break;
}
- Now check whether the security token could be obtained or not. If yes then we create a class from the proxy that has been generated and we add the token acquired to the
RequestSoapContext
of the call.
if (token == null)
throw new ApplicationException( "Unable to obtain security token." );
SecureServiceProxy.Service1Wse proxy =
new client.SecureServiceProxy.Service1Wse();
proxy.RequestSoapContext.Security.Timestamp.TtlInSeconds = 60;
proxy.RequestSoapContext.Security.Tokens.Add( token );
proxy.RequestSoapContext.Security.Elements.Add(new
MessageSignature( token ) );
- Finally call the service.
long a=long.Parse(textLong1.Text);
long b=long.Parse(textLong2.Text);
long result=proxy.perform(a,b);
MessageBox.Show(a + " + " + b + " = " + result.ToString());
Points of Interest
I had forgotten to add the Web Service Enhancements to the WSE 2.0 service and that ate a lot of my time.