View RSS Feed

Development Team Blog

How to Use SOAP Headers to Limit the Lifespan of a WebService Call

Rate this Entry
In this blog I will show you how you can limit the amount of time that an application can call a webservice function. It is a small contribution to security and helps you against unwanted webservice calls.

SOAP Headers
A SOAP based WebService call always contains a body section and optionally can contain a header section. The use of a SOAP header section on both the Visual DataFlex server as well as client side is good documented in the help provided with the product. The good thing of the header section is that one cannot know if it is required and what the contents should be if someone looks at the WSDL. So only if someone intercepts the traffic between server and client it could be known.

A Token Function
The idea of this blog is to create a token that needs to be passed on the next webservice call and this token should only be valid for a certain amount of time. So let us create a token to do that.
Code:
{ Published = True }
{ Description = "Returns a communication token." }
Function CreateToken Returns String
    DateTime dtNow
    String sToken
    
    Move (CurrentDateTime ()) to dtNow
    Get StrToHex of oHexHandler dtNow to sToken
    
    Function_Return sToken
End_Function
As you can see it is a very simple function and if you like you can make it much more complex. Of course you can make the description empty or make the name not so clear and both make it less clear to someone that does not know. The StrToHex function can be found in the conversions library. Since the token has a short lifetime span you either need to call the CreateToken function often or return the next token in the header by the server.

Passing the Retrieved Token
Now the client side that calls our webservice functions need to pass this token with each call. The following code shows how to do that from a Visual DataFlex application.
Code:
Get wsCreateToken of oWSMyService to sToken

Send ClearSoapHeaders of oWSMyService // Removes a header node that was in memory from the last call
Get Create (RefClass (cXmlDomDocument)) to hoXml // Creates an XML object
Get CreateDocumentElementNS of hoXml "http://www.dataaccess.com/secure" "Token" to hoRoot
Set psText of hoRoot to sToken
Send AddSoapHeaderNode of oWSMyService hoRoot
// destroy the XML object
Send Destroy of hoXml
You can make it less clear to a hacker by renaming "Token" to something like "Flower" or "Christmas" or so.

Testing the Passed Token
At server side we need to read the SOAP header section and validate the passed token. The following code does that and the function needs to be called from each of your webservice functions.
Code:
Function ValidateRequest Returns Boolean
    Handle hoXml hoRoot hoNode
    String sToken
    Boolean bIsId bValidRequest
    DateTime dtNow dtToken
    TimeSpan tsDiff

    // get request headers
    Get SoapHeaderRequestNode to hoXml
    If (hoXml <> 0) Begin
        Get DocumentElement of hoXML to hoRoot // should be SOAP header node
        Get FirstChild of hoRoot to hoNode
        // process all headers nodes
        While (hoNode <> 0)
            Get IsElementNS of hoNode "http://www.dataaccess.com/secure" "Token" to bIsId
            If (bIsId) Begin
                Get pstext of hoNode to sToken
            End
            Get NextNode of hoNode to hoNode
        Loop
        // when done, destroy the XML object
        Send Destroy of hoXml
    End
    
    If (sToken <> "") Begin
        Get HexToStr of oHexHandler sToken to dtToken
        Move (CurrentDateTime ()) to dtNow
        Move (dtNow - dtToken) to tsDiff
        Move (SpanTotalMilliseconds (tsDiff) < 5000) to bValidRequest
    End

    Function_Return bValidRequest
End_Function
The above function returns true if the token is present and the time difference between the test and the time of the requested token is less than 5,000 milliseconds. For debugging your webservices I suggest you make the time span bigger (lets say 50,000 milliseconds. The code that calls our ValueRequest function could be:
Code:
{ Published = True }
{ Description = "Returns a list of contact names" }
Function ContactNames Boolean bActive Returns String[]
    String[] sNames
    Boolean bValidRequest
    
    Get ValidateRequest to bValidRequest
    If (bValidRequest) Begin
This is my last contribution for 2011 and I wish all of you a happy 2012!

Updated 31-Dec-2011 at 07:59 AM by Vincent Oorsprong (Made a link to the conversions library)

Categories
Uncategorized

Comments

  1. Anders Ohrt's Avatar
    From a technical perspective this is an interesting technique, but I think itís important to note that from a security perspective this implementation is security through obscurity. If you need to protect your application against someone trying to compromise it, you need to store the time on the server side and pass a token which contains no changeable information to the client. You should always assume all variables sent from the client to be totally under the attackerís control. On each call, you would need to validate the token against a server side session table, and look up the allowed time span from there.
  2. Jakob Kruse's Avatar
    Also, what is the benefit of placing this token in the soap header? Wouldn't it be easier to add a token field to the message body, since it would then be a part of the request struct, and one would not have to create and parse xml data manually?