• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 2991
  • Last Modified:

Simple WebService with Forms Authentication

Hi all!

I'm trying to build a web application that will be compose by two web services.

The first webservice, called AuthenticationWS.asmx will be responsible to authenticate a user with username and password.

The second webservice, called SoftwareInstallWS.asmx will have the methods that the user will use.

The second webservice (SoftwareInstallWS.asmx) should be user ONLY IF the user authenticates against the first one(AuthenticationWS.asmx). So, I did the folowing changes on my web.config file:

    <authentication mode="Forms">
      <forms name="MyAuthenCookie" loginUrl="AuthenticationWS.asmx" protection="All" timeout="60" path="/" />
    </authentication>

On the AuthenticationWS.asmx, I did the folowing:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Security;

namespace WebServiceMaxima
{
    /// <summary>
    /// Summary description for AuthenticationWS
    /// </summary>
    [WebService(Namespace = "http://test.com.br/webservices/")]
    [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 AuthenticationWS : System.Web.Services.WebService
    {

        [WebMethod]
        public string DoLogin(string vUserName, string vPassword)
        {

            string vMessage = string.Empty;
            if (!((vUserName.Trim().ToUpper() == "ADMIN") && (vPassword.Trim().ToUpper() == "TEST")))
            {
                //Define error message
                vMessage = "Invalid username/password";
            }
            else
            {
                //Emits the ticket if the username and password was correct.
                FormsAuthentication.SetAuthCookie(vUserName, true);
            }

            return vMessage;

        }

        [WebMethod]
        public bool DoLogout()
        {

            try
            {
                FormsAuthentication.SignOut();
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
    }
}




On SoftwareInstallWS.asmx, i did:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;

namespace WebServiceMaxima
{
    /// <summary>
    /// Summary description for SoftwareInstall
    /// </summary>
    [WebService(Namespace = "http://test.com.br/webservices/")]
    [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 SoftwareInstallWS : System.Web.Services.WebService
    {

        [WebMethod]
        public string HelloWorld()
        {
            if (!Context.User.Identity.IsAuthenticated)
                throw new UnauthorizedAccessException("Access denied to this webservice");
            return "Hello World";
        }
    }
}



If I call these webservices from a webpage, everything works as expected... Before authenticated (by the first webservice), the second webservice could not be accessed. After authenticated, it can be used as well.

But, when I try to do the same on the consumer application, even when we authenticate to the first webservice, I get the authenticated error when access the second webservice, since the Context.User.Identity.IsAuthenticated remains false.

Here are the code on the consumer:
            AuthenticationWS wsAuth = new AuthenticationWS();
            SoftwareInstallWS wsInstall = new SoftwareInstallWS();

            String vReturn = wsAuth.DoLogin("ADMIN", "TEST");  //Authenticated OK
            vReturn = wsInstall.HelloWorld();   //-<<< ERROR

What Am I doing wrong?
Thanks a lot!
WEB.CONFIG
<authentication mode="Forms">
  <forms name="MyAuthenCookie" loginUrl="AuthenticationWS.asmx" protection="All" timeout="60" path="/" />
</authentication>
 
 
 
AuthenticationWS.asmx
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Security;
 
namespace WebServiceMaxima
{
    /// <summary>
    /// Summary description for AuthenticationWS
    /// </summary>
    [WebService(Namespace = "http://test.com.br/webservices/")]
    [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 AuthenticationWS : System.Web.Services.WebService
    {
 
        [WebMethod]
        public string DoLogin(string vUserName, string vPassword)
        {
 
            string vMessage = string.Empty;
            if (!((vUserName.Trim().ToUpper() == "ADMIN") && (vPassword.Trim().ToUpper() == "TEST")))
            {
                //Define error message
                vMessage = "Invalid username/password";
            }
            else
            {
                //Emits the ticket if the username and password was correct.
                FormsAuthentication.SetAuthCookie(vUserName, true);
            }
 
            return vMessage;
 
        }
 
        [WebMethod] 
        public bool DoLogout()
        {
 
            try
            {
                FormsAuthentication.SignOut();
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
    }
}
 
 
 
 
 
SoftwareInstallWS.asmx
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
 
namespace WebServiceMaxima
{
    /// <summary>
    /// Summary description for SoftwareInstall
    /// </summary>
    [WebService(Namespace = "http://test.com.br/webservices/")]
    [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 SoftwareInstallWS : System.Web.Services.WebService
    {
 
        [WebMethod]
        public string HelloWorld()
        {
            if (!Context.User.Identity.IsAuthenticated)
                throw new UnauthorizedAccessException("Access denied to this webservice");
            return "Hello World";
        }
    }
}
 
 
 
 
 
CONSUMMER APPLICATION
AuthenticationWS wsAuth = new AuthenticationWS();
SoftwareInstallWS wsInstall = new SoftwareInstallWS();
 
String vReturn = wsAuth.DoLogin("ADMIN", "TEST");  //Authenticated OK
vReturn = wsInstall.HelloWorld();   //-<<< ERROR

Open in new window

0
regisdaniel
Asked:
regisdaniel
1 Solution
 
DiarenCommented:
Hi regisdaniel,

In AuthenticationWS.DoLogin all that was called is SetAuthCookie which as stated in the MSDN only applies to the next request made by the Browser (http://msdn.microsoft.com/en-us/library/system.web.security.formsauthentication.setauthcookie.aspx)

What needs to happen is the User for the current request needs to be updated, which is done using the FormsAuthenticationTicket hidden within the SetAuthCookie method.

An example is attached
[WebMethod]
public string DoLogin(string vUserName, string vPassword)
{
    string vMessage = string.Empty;
    if (!((vUserName.Trim().ToUpper() == "ADMIN") && (vPassword.Trim().ToUpper() == "TEST")))
    {
        //Define error message
        vMessage = "Invalid username/password";
    }
    else
    {
        // Get the cookie to be issued to the browser
        HttpCookie cookie = FormsAuthentication.GetAuthCookie(vUserName, true);
        
        // Extract the ticket
        FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value);
        
        // Create the new identity for this request
        FormsIdentity identity = new FormsIdentity(ticket);
 
        // Apply it.
        Context.User = new System.Security.Principal.GenericPrincipal(identity, null);
        Context.Response.Cookies.Add(cookie);
    }
 
    return vMessage;
}

Open in new window

0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Tackle projects and never again get stuck behind a technical roadblock.
Join Now