Passing FormsAuthentication cookie to a WCF service

asp.net, forms-authentication, wcf, wcf-security

Solution

It sounds like you're looking for the Windows Communication Foundation Authentication Service.

EDIT:

After re-reading the question more carefully (and after Ariel's comment) I'd like to retract the above suggestion. The WCF Authentication Service won't add much to this scenario.

I haven't done this between WCF and ASP.NET, however I have configured ASP.NET applications to share forms authenticated users, perhaps I can help in some way.

To ensure that both applications can encrypt/decrypt the forms authentication cookie in the same way you should configure the `<machineKey>` element for both applications (in web.config or machine.config depending on whether you want to do this at the machine or application level). You should look at the `validation`, `validationKey`, `decryption` and `decryptionKey` attributes.

Ensure that your `<forms>` elements in both web.config files are configured similarly. Specifically the `name`, `path` and `domain` attributes.

It's likely that this only applies to cookies passed to/from a web browser (but may be useful in this case): To allow cookies to be passed between the websites www.foo.com and bar.foo.com you would configure the `forms` element as follows to allow cookies to be set on one site and successfully passed to the other:

<forms ... domain=".foo.com" ... />

Passing the cookie to the WCF service is likely to be the tricky bit. I'm not very experienced with WCF, so I've adapted code from kennyw.com:

HttpRequestMessageProperty httpRequestProperty = new HttpRequestMessageProperty();
httpRequestProperty.Headers.Add(HttpRequestHeader.Cookie, "<Forms Authentication Cookie>");

using (OperationContextScope scope = new OperationContextScope(serviceClient.InnerChannel))
{
  OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty;
  serviceClient.MethodName();
} 

If you're hosting WCF within IIS (and not self-hosting) you can pass the WCF request through the ASP.NET processing pipeline by setting

<system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" ... />
</system.serviceModel>

If you're self hosting you could examine the request headers using the incoming message's properties in `OperationContext.Current.IncomingMessageProperties` and get the forms authentication cookie value and decrypt it using `FormsAuthentication.Decrypt(string)`.

I have no idea whether any of this would work, but would love to hear if it does!

Problem

I have a website that talks to a remote WCF web service. Both use the same custom FormsAuthentication Provider. I would like to authenticate with the WCF service impersonating the user currently logged in the site. I already did this manually, using UserName client credentials but I need to know the user password. So, what works so fart is this: an authenticated user makes a request, I create a Service Client and set his credentials: ``` serviceClient.ClientCredentials.UserName.UserName = username; serviceClient.ClientCredentials.UserName.Password = password; ``` But what I really want is to pass the FormsAuthentication cookie directly, because I don't want to store the user password. Any ideas?

Original source