locked
Trying to secure our webservice RRS feed

  • Question

  • User1324895001 posted

    We have been working on a webservice for a bit now going thru testing and such, but now that we are getting closer to production time, we want to enable security within the web service. we are hosting the web service on the same server as our web site, but as its own. So if possible, since we will be connecting to the same database as the site does, we would like to see about using the membership provider to authenticate against the database before allowing anyone to use the services exposed.

     

    This link has an example(dated 2010) but cant seem to modify the sample code to connect to our database for the authentication.
    http://dotnetslackers.com/articles/aspnet/Securing-ASP-Net-Web-Services-with-Forms-Authentication.aspx

    I know it has nothing to do with the connection string because we can execute all our web calls and get data and send data, but everytime we try the test calls the SoapHeader is always null

            public SecuredWebServiceHeader SoapHeader;
    
            [WebMethod]
            [System.Web.Services.Protocols.SoapHeader("SoapHeader")]
            public string AuthenticateUser()
            {
                if (SoapHeader == null)
                    return "Please provide a Username and Password";
                if (string.IsNullOrEmpty(SoapHeader.Username) || string.IsNullOrEmpty(SoapHeader.Password))
                    return "Please provide a Username and Password";
                // Are the credentials valid?
                if (!IsUserValid(SoapHeader.Username, SoapHeader.Password))
                    return "Invalid Username or Password";
                // Create and store the AuthenticatedToken before returning it
                string token = Guid.NewGuid().ToString();
                HttpRuntime.Cache.Add(
                    token,
                    SoapHeader.Username,
                    null,
                    System.Web.Caching.Cache.NoAbsoluteExpiration,
                    TimeSpan.FromMinutes(60),
                    System.Web.Caching.CacheItemPriority.NotRemovable,
                    null);
                return token;
            }
    
            private bool IsUserValid(string Username, string Password)
            {
                return System.Web.Security.Membership.ValidateUser(Username, Password);
            }
    
            private bool IsUserValid(SecuredWebServiceHeader SoapHeader)
            {
                if (SoapHeader == null)
                    return false;
                // Does the token exists in our Cache?
                if (!string.IsNullOrEmpty(SoapHeader.AuthenticatedToken))
                    return (HttpRuntime.Cache[SoapHeader.AuthenticatedToken] != null);
                return false;
            }
    
            [WebMethod]
            [System.Web.Services.Protocols.SoapHeader("SoapHeader")]
            public string HelloWorld()
            {
                if (!IsUserValid(SoapHeader))
                    return "Please call AuthenitcateUser() first.";
                return "Hello " + HttpRuntime.Cache[SoapHeader.AuthenticatedToken];
            }

    The simple test above always returns null and never authenticates the user. Can anyone offer any suggestions or links to updated samples online that may help?


     

    Friday, September 27, 2013 5:40 PM

All replies

  • User1324895001 posted

    Im debugging the service and thats where im not seeing any of it work.. I have not built a client app to test from..

    Monday, September 30, 2013 9:52 AM
  • User-760709272 posted

    Just debugging the methods, the soapheader is always going to be null unless the debugger page gives you the option of supplying the values.  I'd try building a test client that calls the method and adds the soapheader and see if it starts to work.

    Monday, September 30, 2013 12:00 PM
  • User1324895001 posted

    Just debugging the methods, the soapheader is always going to be null unless the debugger page gives you the option of supplying the values.  I'd try building a test client that calls the method and adds the soapheader and see if it starts to work.

     

    i can create the client app, any chance you can provide a link to how to send the soapheader? I found a few, but not super clear on implementing it..

    Ill post back today with my results

     

    thanks...

     

    Tuesday, October 1, 2013 10:23 AM
  • User-760709272 posted

    Code can be found in above links.

    Tuesday, October 1, 2013 10:29 AM
  • User1324895001 posted

    I have run through those links and confused on how to send the data from my client app to the web service. I have for testing purposes already setup the logic as provided in link #2, that is all setup and configured within my webservice (asmx file)

    Now i created a simple client app that has 2 text boxes and a button. In the button event i can access my web service and can get to all my methods currently public, but how do i send the header data along with the textbox data that my method requires? Below is what i have so far but the 3 lines that have to do with the header are not really doing anything

     

    namespace WebServiceClient
    {
        public class SecuredWebServiceHeader : System.Web.Services.Protocols.SoapHeader
        {
            public string Username;
            public string Password;
            public string AuthenticatedToken;
        }
    
    
        public partial class _Default : System.Web.UI.Page
        {
            protected void Page_Load(object sender, EventArgs e)
            {
    
            }
    
            protected void Button1_Click(object sender, EventArgs e)
            {
                AppServices fws = new AppServices();
                SecuredWebServiceHeader sh = new SecuredWebServiceHeader();
    
                sh.Username = "xxxxxx";
                sh.Password = "xxxxxx";
    
                int ret = 0;
                ret = fws.WebServiceInsert(TextBox1.Text, TextBox2.Text);
                Label1.Text = ret.ToString();
            }
        }
    }
    

    Tuesday, October 1, 2013 11:42 AM
  • User-760709272 posted

    This is my service code

    public class SecuredWebServiceHeader : System.Web.Services.Protocols.SoapHeader
    {
        public string Username;
        public string Password;
        public string AuthenticatedToken;
    }
    
    /// <summary>
    /// Summary description for SecureService
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // 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 SecureService : System.Web.Services.WebService
    {
        public SecuredWebServiceHeader SoapHeader;
    
        [WebMethod]
        [System.Web.Services.Protocols.SoapHeader("SoapHeader")]
        public string HelloWorld()
        {
            return "Hello World";
        }
    }

    The .net client

    SecureService ss = new SecureService();
    
    SecuredWebServiceHeader h = new SecuredWebServiceHeader();
    h.Username = "user";
    h.Password = "password";
    ss.SecuredWebServiceHeaderValue = h; // this is the line you're missing
    
    Console.WriteLine(ss.HelloWorld());
    Console.ReadLine();
    

    Tuesday, October 1, 2013 12:48 PM
  • User1324895001 posted

    thanks

    i was able to get it to work after publishing to the server since some of the methods werent exposed..

    I setup like your example, but noticed one thing, the header is being set and method being executed, but to test to see if it will fail with no header and it still executed the method even if i disabled the header detail.

    I have this above my method in the webservice

    [System.Web.Services.Protocols.SoapHeader("SoapHeader")]

    Do i need to add something else to the method or within the method to insure that the user is authenticated before the method is executed?

    Do i need to wrap my logic inside a condition like this

    if (!IsUserValid(SoapHeader))



     

     

     

    Tuesday, October 1, 2013 5:09 PM
  • User1324895001 posted

    Also something else i noticed is that the AuthenticatedToken isnt being set, so even when i provide a login, its returning null and failing when it checks for it..

    Is there something i need to change? do i need to use that?

    Tuesday, October 1, 2013 6:07 PM