views:

96

answers:

1

Hopefully you folks can clarify some of this for me. I have a web-application using the Sql Membership Provider and it talks to a second web-application through a WCF Service. Both applications share the same Sql Membership Provider datastore...but I need each WCF Service call to authenticate the user.

Now, I've looked at a LOT of samples, but I feel like the samples I've seen either leave out certain code because it "should" be obvious to me, or I mis-understand how WCF handles the request (see expected code below).

I'm grateful for any help...

HERE'S WHAT I ALREADY KNOW HOW TO DO

  1. I know how to configure the Sql Membership on both ends.
  2. I know how to setup the wsHttpBinding
  3. I know how to setup the services certificate used in transport security

HERE'S WHAT I AM CONFUSED ON

  1. How can I pass the Membership password (...you can't)
  2. Do I pass the authentication cookie? If so, how?
  3. Do I create a "known" username and password not related to the user (themselves)?

IN THE WEB CLIENT I WOULD EXPECT TO SEE CODE SOMETHING LIKE THIS

protected void btnLogin_Click(object sender, EventArgs e)
{
    // Logging into the web-application is known and easy.
    if (Membership.ValidateUser("MyUserName", "MyPassword"))
    {
        FormsAuthentication.SetAuthCookie("MyUserName", true);
        FormsAuthentication.RedirectFromLoginPage("MyUserName", false);
    }
}

protected ServiceReference1.Contractor getContractor(Int32 key)
{
    // I expect something "like" this on the client call.
    MembershipUser user = Membership.GetUser("MyUserName");

    ServiceReference1.FishDataClient wcfService = new ServiceReference1.FishDataClient();

    // You can't retreive the users password directly,
    // nor can you get the hash from the SqlMembershipProvider.
    wcfService.ChannelFactory.Credentials.UserName.UserName = user.UserName;
    // So doing something like this would not be possible.
    wcfService.ChannelFactory.Credentials.UserName.Password = "??????";

    // So how is the web service going to authenticate the user from it's
    // references to the same SqlMembershipProvider (database).
    ServiceReference1.Contractor contractor = wcfService.GetContractor(key);

    wcfService.Close();
    wcfService = null;

    return contractor;
}

IN THE WCF SERVICE I WOULD EXPECT TO SEE CODE SOMETHING LIKE THIS

[PrincipalPermission(SecurityAction.Demand, Role = "User")]
public Contractor GetContractor(Int32 key)
{
    ServiceSecurityContext context = ServiceSecurityContext.Current;
    Contractor contractor = new Contractor();

    // What goes here?  I would expect something like this...
    if (Membership.ValidateUser("???????", "???????"))
        contractor.Get(key);

    return contractor;
}
A: 

I'm assuming your WCF membership provider and your web application membership provider are using the same backend user set.

If so you would want to share authentication cookies between the applications. You can find more information on how to do that here.

Next you need to pass the authentication cookie that came with the web application request to the WCF service call. You can see how to do that here.

The idea is the user logs into your web application and by doing so is logged into your WCF service.

Daniel
Q: How does passing the cookie help to enforce the "SecurityAction.Demand" above?
Other examples online "say" you can pass credentials from the client, such that, WCF checks the Sql Membership and enforces the "Role" located in the "SecurityAction.Demand". My issue is HOW does WCF know how to do this? Is it handled "under the hood" black-box style?
When the user is authenticated an object is created that implements the IIdenty interface. The demand will use this object to enforce the check. The IIdentity object will be created by the Membership provider when the user is authenticated using the information in the cookie.
Daniel