R – Authenticating ASP.NET web app with WCF service

asp.netwcfweb services

Background

I have an ASP.NET web application that interacts with WCF services. The web application and the WCF services are under my control. The ASP.NET web application uses a custom implementation of the ASP.NET Membership Provider Model (with passwords stored in hashed form) to authenticate users who log in to the web application. Both the ASP.NET web application and WCF services have access to the same membership database.

Since the users will supply their password only once, and I don't want to have to store their passwords anywhere or annoy them by repeatedly asking them to resupply their password, I need an appropriate mechanism to authenticate the users with the WCF services.

Based on other questions and answers I have seen, I am considering a sort of "login session" approach, where a login session will be created in the custom membership database when the user initially logs in to the web application, with the login session identified by a GUID, and automatically expired after a period of inactivity. The login session GUID will be "remembered" by the web application for each logged in user (either stored in the Forms Authentication Ticket or in the session).

The WCF service will also provide its own login operation accepting a user name and password and returning a login session GUID as described above.

The WCF service would then accept the login session GUID for all other operations, and verify that the GUID represents a valid login session that has not expired before allowing the operation to proceed.

I have done quite a bit of background reading on this, and there is a lot of material on straightforward use of the UserName client credential type, but this would require the web application to remember the user's password, which doesn't seem like a great idea to me.

I've done some research and found material on MSDN, but this seems like a lot of effort to implement what (to me at least) seems like a pretty common usage scenario.

How to: Create a Custom Token

Question

Is the general approach of the "login session" described above reasonable?
If so, what is the best way to achieve it?
If not, can you suggest an alternative?

Best Answer

This is a very reasonable approach.

To do this you setup your service endpoint and configure it with your custom membership provider (You can do the same with SQL membership provider, it doesn't require a custom one).

On the web application you set up the Authenticate event of the Login control to instantiate a new service proxy and set the username/password in the ClientCredentials in the proxy.

Now when you make the call to the Service through the proxy WCF will pass these credentials through the secure channel to the service and use them for authentication.

Now you simply need to store the proxy in session and use it for future access to the service as it has the channel state and a private key.

protected void LoginControl_Authenticate(object sender, AuthenticateEventArgs e)
{
    bool Authenticated = false;
    try
    {
        MyServiceClient proxy = new MyServiceClient("MyServiceEndpoint");
        proxy.ClientCredentials.UserName.UserName = LoginControl.UserName;
        proxy.ClientCredentials.UserName.Password = LoginControl.Password;

        //It doesn't really matter what is called or what it does because 
        //Membership Provider for the Service does the authentication.
        string retval = proxy.login("Logging in"); 

        //Now that channel is established the proxy needs to be kept
        //since it contains the channel state which includes a private key
        Session["MyServiceProxy"] = proxy;  
        Authenticated = true;
    }
    catch (Exception ex)
    {
        //Login Error...
    }
    e.Authenticated = Authenticated;
}