Click here to Skip to main content
11,438,069 members (47,402 online)
Click here to Skip to main content

Web Service Authentication

, 25 Nov 2009 CPOL
Rate this:
Please Sign up or sign in to vote.
A simple mechanism to authenticate users to a WebService

Sample Image - WebServiceAuthentication.gif

Introduction

This is a simple mechanism to authenticate users to a Web Service, using a Time Token and MD5 Hashing to encrypt password.

Background

In CodeProject, you can find at least two others' mechanism to authenticate users to a Web Service. Dan_P wrote Authentication for Web Services as a Simple authentication for web services using SOAP headers. But the username and password are sent in clear text and there is no encryption for the data. HENDRIK R. is the author of An introduction to Web Service Security using WSE, that is really a complete solution, but too much complicated for my purposes. The username is sent in clear text, but it is possible to use Password Digest to encrypt the password. The data are encrypted using XML Encryption specification to encrypt portions of the SOAP messages.

My solution is something in the middle of the above two. The username is sent in clear text, but I use MD5 to encrypt the password. I do not need to send sensitive data, so the data returned by the Web Service is not encrypted.

Using the Code

The basic idea is to send UserName and Password from the client to the Web Service using MD5 Hash Code as encryption system. In this way, the password never travels in clear over the network. The Web Service retrieves the user password from a DB or anything else and uses the same MD5 algorithm to test if the password is correct. To be sure that if someone intercepts the Hash, this can be used to authenticate in a later time, I added a timestamp before hashing the Key string. Last, as we are not always on the same server and/or the client clock may be in a different Time Zone or simply not synchronized, I added the possibility to request a Token containing the time mark to the server.

I provided a sample in ASP.NET C# for the client side, but it is possible to use any language: ASP classical JScript or VBScript, PHP, Python, etc. Anyway, on the client side we need to build up the Key using UserName, Password and the hashed timestamp Token previously got from the same Web Service. We can then call the Service and we will get the answer (or an authentication failure warning) that is displayed on the web page.

private void ButtonUseToken_Click(object sender, System.EventArgs e)
{
    string ret;
    string UserName, Password, ServiceName, Token;
    string Key, ToHash;

    UserName=this.TextBoxUserName.Text;
    Password=this.TextBoxPwd.Text;
    ServiceName=this.TextBoxService.Text;
    Token=this.TextBoxToken.Text;
    ToHash=UserName.ToUpper()+"|"+Password+"|"+Token;
    Key=Hash(ToHash)+"|"+UserName;

    ServicePointReference.ServicePoint Authenticate = 
                             new ServicePointReference.ServicePoint();
    ret=Authenticate.UseService(Key, ServiceName);
    this.ServResponse.Text=ret;
}

The MD5 Hash procedure is very simple in C#; this one was written by Vasudevan Deepak Kumar in Securing Web Accounts.

private string Hash(string ToHash)
{
    // First we need to convert the string into bytes,
    // which means using a text encoder.
    Encoder enc = System.Text.Encoding.ASCII.GetEncoder();

    // Create a buffer large enough to hold the string
    byte[] data = new byte[ToHash.Length];
    enc.GetBytes(ToHash.ToCharArray(), 0, ToHash.Length, data, 0, true);

    // This is one implementation of the abstract class MD5.
    MD5 md5 = new MD5CryptoServiceProvider();
    byte[] result = md5.ComputeHash(data);

    return BitConverter.ToString(result).Replace("-", "").ToLower();
}

On Web Service server side, I implemented just three Web Methods:

GetToken is used to get the Time-marked token. The token you get this way is intended to be used in the basic Authenticate method, or in the UseService that can also verify the access rights for the users authenticated to the requested service. The core of the system is implemented by TestHash. Here the password is hard-coded, but in the sample provided, you have also the code to get it from a database:

private bool TestHash (string HashStr, 
             string UserName, int minutes, string ServiceName)
{
    string Pwd, ToHash;
    string sResult, sResultT, sResultToken;
    try
    {
        // JUST FOR TEST: the password is hard-coded:
        Pwd="SeCrEt";

        DateTime dt = DateTime.Now;
        System.TimeSpan minute = new System.TimeSpan(0,0,minutes,0,0);
        dt = dt-minute;
        //before hashing we have:
        //USERNAME|PassWord|YYYYMMDD|HHMM
        ToHash=UserName.ToUpper()+"|"+Pwd+"|"+dt.ToString("yyyyMMdd")+
                                             "|"+dt.ToString("HHmm");
        sResult = Hash(ToHash);
        //TokenWeGotBefore
        ToHash=dt.ToString("yyyyMMdd")+"|"+dt.ToString("HHmm");
        sResultToken = Hash(ToHash);
        //USERNAME|PassWord|TokenWeGotBefore
        ToHash=UserName.ToUpper()+"|"+Pwd+"|"+sResultToken;
        sResultT = Hash(ToHash);
    
        if ((sResult==HashStr) || (sResultT==HashStr)) 
            return true;
        else
            if (minutes==0) // allowed max 2 minutes - 1
                            // second to call web service
            return TestHash (HashStr, UserName, 1, ServiceName);
        else
            return false;
    }
    catch
    {
        return false;
    }
}

To request a hashed time-stamped Token to the Web Service, the method is:

[WebMethod]
public string GetToken ()
{
    string ToHash, sResult;
    DateTime dt = DateTime.Now;
    ToHash=dt.ToString("yyyyMMdd")+"|"+dt.ToString("HHmm");
    sResult = Hash(ToHash);
    return sResult;
}

The method that checks the user authentication is also kept very simple; in a real application you normally need to access a database to check the authentication level and may need to return some data to the caller:

[WebMethod]
public string UseService (string Key, string ServiceName)
{
    string [] HashArray;
    string UserName, level;

    // Key string: HASH|User|OptionalData
    HashArray=Key.Split('|');
    level = "-1";    //default level

    if (TestHash(HashArray[0], HashArray[1], 0, ServiceName))
    {
        try
        {
            UserName=HashArray[1];
            // JUST FOR TEST: the User authentication level is hard-coded
            // but may/should be retrieved from a DataBase
            switch (UserName)
            {
                case "MyUserName":
                    level="1";
                    break;
                case "OtherUser":
                    level="2";
                    break;
                default:
                    level="-1";
                    break;
            }
            if (level=="1") return "YOU ARE AUTHORIZED";
        }
        catch (Exception exc)
        {
            return "Authentication failure: " + exc.ToString();
        }
    }
    return "Authentication failure";
}

Points of Interest

TestHash checks to see if the Hash contains a timestamp or an already-hashed token, and calls itself once again in case of failure: if someone is calling the service, let's say, at 11:34:58 the Key is valid from 11:34:00 until 11:35:59, that is during two minutes minus one second.

The client side may be implemented in any language: ASP classical, JScript or VBScript, PHP, Python, etc. I have the intention to post this code too next time...

History

  • 01/20/2005 - Article created
  • 11/25/2009 - Updated source code

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

faina
Web Developer
Italy Italy
No Biography provided

Comments and Discussions

 
QuestionExpired in 24 hours Pin
dkosasih22-Sep-14 16:59
memberdkosasih22-Sep-14 16:59 
GeneralMy vote of 5 Pin
Aamer Alduais12-Oct-12 22:06
memberAamer Alduais12-Oct-12 22:06 
GeneralRe: My vote of 5 Pin
faina12-Oct-12 23:10
memberfaina12-Oct-12 23:10 
GeneralRe: My vote of 5 [modified] Pin
Aamer Alduais4-Nov-12 21:11
memberAamer Alduais4-Nov-12 21:11 
GeneralMy vote of 5 Pin
Jack_32127-May-12 5:07
memberJack_32127-May-12 5:07 
GeneralMy vote of 1 Pin
ali32b17-Nov-10 10:45
memberali32b17-Nov-10 10:45 
GeneralNOBODY wants to answer the 404 Page Not Found question Pin
LawrenceMayo29-Jun-09 15:57
memberLawrenceMayo29-Jun-09 15:57 
I have pored through the comments on this sample code. Several people have asked why there is a 404 error upon running the thing. I set the TestAuth.aspx as the default, begin debugging, and BOOM when I click ANY button, it's 404.

I've gone to IIS manager, I've set this up as an application directory, ... Nada. 404, baby.

Any ideas or do I throw this code away and look for something else?
GeneralRe: NOBODY wants to answer the 404 Page Not Found question Pin
faina25-Nov-09 0:33
memberfaina25-Nov-09 0:33 
Generalattempting to change the time feature. Pin
charles Frank15-Jun-09 5:51
membercharles Frank15-Jun-09 5:51 
GeneralRe: attempting to change the time feature. Pin
faina25-Nov-09 0:08
memberfaina25-Nov-09 0:08 
GeneralJust wanted to say thanks, Pin
pimpmurph7-Aug-07 8:49
memberpimpmurph7-Aug-07 8:49 
Generalneed help on the source code files [modified] Pin
Cheng Dehua12-Apr-07 18:02
memberCheng Dehua12-Apr-07 18:02 
GeneralRe: need help on the source code files Pin
faina18-Apr-07 22:16
memberfaina18-Apr-07 22:16 
GeneralRe: need help on the source code files Pin
Cheng Dehua18-Apr-07 22:44
memberCheng Dehua18-Apr-07 22:44 
GeneralFalse sense of security Pin
DEGT5-Apr-07 22:25
memberDEGT5-Apr-07 22:25 
GeneralRe: False sense of security Pin
faina5-Apr-07 23:52
memberfaina5-Apr-07 23:52 
GeneralRe: False sense of security Pin
Dewey19-Apr-07 23:00
memberDewey19-Apr-07 23:00 
QuestionRe: False sense of security Pin
diegotegravi30-Aug-07 10:14
memberdiegotegravi30-Aug-07 10:14 
AnswerRe: False sense of security Pin
Chona11712-May-12 21:55
memberChona11712-May-12 21:55 
QuestionWhat should be the setting in IIS [modified] Pin
nzhuda13-Dec-06 16:47
membernzhuda13-Dec-06 16:47 
GeneralHelp me!! Pin
omkarphatak2-Dec-06 8:01
memberomkarphatak2-Dec-06 8:01 
GeneralRe: Help me!! Pin
faina3-Dec-06 21:07
memberfaina3-Dec-06 21:07 
GeneralRe: Help me!! Pin
omkarphatak4-Dec-06 18:46
memberomkarphatak4-Dec-06 18:46 
GeneralRe: Help me!! Pin
ashit197825-Sep-07 11:36
memberashit197825-Sep-07 11:36 
Generalneed help on running this project Pin
m-xi1-Mar-06 5:55
memberm-xi1-Mar-06 5:55 
GeneralRe: need help on running this project Pin
faina1-Mar-06 21:37
memberfaina1-Mar-06 21:37 
GeneralRe: need help on running this project Pin
m-xi6-Mar-06 3:30
memberm-xi6-Mar-06 3:30 
GeneralRe: need help on running this project Pin
Cheng Dehua14-Apr-07 20:57
memberCheng Dehua14-Apr-07 20:57 
GeneralRe: need help on running this project Pin
Cheng Dehua18-Apr-07 21:46
memberCheng Dehua18-Apr-07 21:46 
QuestionUnencrypted Text ? Pin
Eniac014-Nov-05 4:44
memberEniac014-Nov-05 4:44 
AnswerRe: Unencrypted Text ? Pin
faina14-Nov-05 23:21
memberfaina14-Nov-05 23:21 
GeneralRe: Unencrypted Text ? Pin
SmirkinGherkin25-Nov-09 7:19
memberSmirkinGherkin25-Nov-09 7:19 
GeneralRe: Unencrypted Text ? Pin
faina25-Nov-09 8:17
memberfaina25-Nov-09 8:17 
Generalnamespaces Pin
Hirahi.9-Aug-05 0:50
memberHirahi.9-Aug-05 0:50 
GeneralAuthentication failure Pin
baltika28-Apr-05 6:06
memberbaltika28-Apr-05 6:06 
GeneralI get error running this project Pin
FMGToronto19-Apr-05 10:59
memberFMGToronto19-Apr-05 10:59 
GeneralRe: I get error running this project Pin
FMGToronto19-Apr-05 11:26
memberFMGToronto19-Apr-05 11:26 
GeneralRe: I get error running this project Pin
moreno13-Mar-09 4:36
membermoreno13-Mar-09 4:36 
Generalbetter implementation Pin
ashish desai31-Jan-05 6:28
memberashish desai31-Jan-05 6:28 
GeneralRe: better implementation ? Pin
faina1-Feb-05 21:06
memberfaina1-Feb-05 21:06 
GeneralTimestamp alternative Pin
Burkovsky26-Jan-05 0:20
memberBurkovsky26-Jan-05 0:20 
GeneralRe: Timestamp alternative Pin
faina26-Jan-05 0:23
memberfaina26-Jan-05 0:23 
QuestionWhat about WSE??? Pin
doogie20-Jan-05 7:25
memberdoogie20-Jan-05 7:25 
AnswerRe: What about WSE??? Pin
faina20-Jan-05 22:39
memberfaina20-Jan-05 22:39 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.150506.1 | Last Updated 25 Nov 2009
Article Copyright 2005 by faina
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid