WCF Error: Invalid token for impersonation - it cannot be duplicated.

WCF Error: Invalid token for impersonation - it cannot be duplicated.

Old forum URL: forums.lhotka.net/forums/t/2440.aspx


billa1972 posted on Tuesday, February 27, 2007

Hi,

Any one else get this error? 

I just downloaded latest from SVN trunk to play with WCF integration and I am getting the above error in the Dataportal.Client.WcfProxy.Fetch method.  I've tried all sort of configurations in the app.config and can't find much on google about this error. The host is IIS and the Service.svc file looks like:

<% @ServiceHost Language=VB Debug="true" Service="Csla.Server.Hosts.WcfPortal" %>

I'm using the following in my app.config & web.config, and I get the same error without any bindingConfiguration (by the way, this was generated from the svcutil in win sdk.)

App.Config
<
system.serviceModel>
<
bindings>
<
wsHttpBinding>
<
binding name="WSHttpBinding_IWcfPortal" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
allowCookies="false">
<
readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<
reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<
security mode="Message">
<
transport clientCredentialType="Windows" proxyCredentialType="None" realm="" />
<
message clientCredentialType="Windows" negotiateServiceCredential="true"
algorithmSuite="Default" establishSecurityContext="true" />
</
security>
</
binding>
</
wsHttpBinding>
</
bindings>

<client>
<
endpoint address="http://localhost/eFileServices/Service.svc"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IWcfPortal"
contract="Csla.Server.Hosts.IWcfPortal" name="WcfDataPortal">
<
identity>
<
userPrincipalName value="MyMachineName\ASPNET" />
</
identity>
</
endpoint>
</client>

</system.serviceModel>

Web.config looks like (generated from the Service Config Editor from sdk):

<system.serviceModel>
<
diagnostics>
<
messageLogging logEntireMessage="true" logMalformedMessages="true"
logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="true" />
</
diagnostics>
<
behaviors>
<
serviceBehaviors>
<
behavior name="MetadataBehavior">
<
serviceMetadata httpGetEnabled="true" />
<
serviceDebug includeExceptionDetailInFaults="true" />
</
behavior>
</
serviceBehaviors>
</
behaviors>
<
services>
<
service behaviorConfiguration="MetadataBehavior" name="Csla.Server.Hosts.WcfPortal">
<
endpoint address="http://localhost/eFileServices/Service.svc"
binding="wsHttpBinding" contract="Csla.Server.Hosts.IWcfPortal" />
</
service>
</
services>
</
system.serviceModel>

ajj3085 replied on Wednesday, February 28, 2007

This is the old double hop issue, but I can't be sure because I've not dived into Wcf. 

I hit this myself using .Net remoting..

RockfordLhotka replied on Wednesday, February 28, 2007

Why are you specifying the userPrincipalName on the client?

I think Andy is right - by doing that, you are causing the client to start with that token and pass it to the app server, which probably works. But if the app server then tries to use SSPI to talk to the database you'll blow up because an impersonated token can't be re-impersonated.

If you can use different credentials to get from the client to the app server (either the user's crednetials or allow anonymous access to the vroot) that should resolve the issue.

sacarro replied on Wednesday, September 10, 2008

Has anybody found a solution for this yet? I have a standalone application server running my wcf services and IIS running a web application that hosts my CSLA objecst. When I make the dataportal call from the webserver, it gives the invalid token error. The web.config has the following security set up:
<authentication mode="Windows"/>     
....
 <security mode="Transport">
            <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
            <message clientCredentialType="Windows" />
</security>

which is what I want. Does anybody have a solution? Or should I just set up a wcf client call in my CSLA dataportal and run them all dataportal operation locally in order to keep security?

Thanks,
~Sam

RockfordLhotka replied on Wednesday, September 10, 2008

What would you do differently in your config, or setting up the proxy, to get your manual WCF calls to work?

 

In other words, the data portal is just using WCF. Why do you think using a “direct” service call will work any differently?

 

Or to put it yet another way, if you can get a “direct” call to work, what did you do in the config or proxy initialization that is different from what the data portal does? That should shed some light on what needs to be done with the data portal (config or WcfProxy code) to make it work.

 

Rocky

 

 

From: sacarro [mailto:cslanet@lhotka.net]
Sent: Wednesday, September 10, 2008 7:59 AM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] WCF Error: Invalid token for impersonation - it cannot be duplicated.

 

Has anybody found a solution for this yet? I have a standalone application server running my wcf services and IIS running a web application that hosts my CSLA objecst. When I make the dataportal call from the webserver, it gives the invalid token error. The web.config has the following security set up:
<authentication mode="Windows"/>     
....
 <security mode="Transport">
            <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
            <message clientCredentialType="Windows" />
</security>

which is what I want. Does anybody have a solution? Or should I just set up a wcf client call in my CSLA dataportal and run them all dataportal operation locally in order to keep security?

Thanks,
~Sam


sacarro replied on Wednesday, September 10, 2008

I think this is what you were asking for This the web code to get the service calls:

// Works
  using (ServiceClient client = new ServiceClient())
            {
                ClientNameLiteral.Text =  client.GetName();
            }
// Impersonation Issue
            CslaClient wcfCslaClient = CslaClient .GetName();


The config:

 <endpoint address="net.tcp://localhost:8765/Service/ServiceClient"
          binding="netTcpBinding" bindingConfiguration="ServiceClientBinding"
          contract="Service.ServiceClient"
          name="ServiceClient">
      </endpoint>
      <endpoint name="WcfDataPortal"
                address=""net.tcp://localhost:8765/Service/CslaDataPortal/"
                binding="netTcpBinding"
                bindingConfiguration="ServiceClientBinding"
                contract="Csla.Server.Hosts.IWcfPortal">
      </endpoint>

RockfordLhotka replied on Monday, September 15, 2008

So basically you need some way to alter or customize the proxy object before it is used?

 

That makes sense. I was recently talking to Miguel Castro about a similar scenario, and I think the answer is to alter WcfProxy so the proxy is a protected member. That way you can subclass WcfProxy and alter the actual WCF proxy object as needed based on various security configurations.

 

You can already subclass WcfProxy to change the endpoint name used from the config file – this would just be one extra feature in that same vein.

 

Rocky

 

 

From: sacarro [mailto:cslanet@lhotka.net]
Sent: Wednesday, September 10, 2008 9:20 AM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] RE: WCF Error: Invalid token for impersonation - it cannot be duplicated.

 

I think this is what you were asking for This the web code to get the service calls:

// Works
  using (ServiceClient client = new ServiceClient())
            {
                ClientNameLiteral.Text =  client.GetName();
            }
// Impersonation Issue
            CslaClient wcfCslaClient = CslaClient .GetName();


The config:

 <endpoint address="net.tcp://localhost:8765/Service/ServiceClient"
          binding="netTcpBinding" bindingConfiguration="ServiceClientBinding"
          contract="Service.ServiceClient"
          name="ServiceC lient">
      </endpoint>
      <endpoint name="WcfDataPortal"
                address=""net.tcp://localhost:8765/Service/CslaDataPortal/"
                binding="netTcpBinding"
                bindingConfiguration="ServiceClientBinding"
                contract="Csla.Server.Hosts.IWcfPortal">
      </endpoint>


RockfordLhotka replied on Monday, September 15, 2008

I put a test release of 3.5.2 online just now, and it includes a couple virtual methods in WcfProxy that you should be able to use to alter the channel factory and proxy objects.

You can override GetChannelFactory() to initialize (or even create your own) ChannelFactory<IWcfPortal>. The base implementation simply creates the channel factory, so you could do this:

protected override ChannelFactory<IWcfPortal> GetChannelFactory()
{
  var f = base.GetChannelFactory();
  // set properties of f here
  return f;
}

You can do the same thing with GetProxy(), which is responsible for creating the proxy based on the channel factory.

I think you can use these methods to set nearly any security-related (or other) properties or values necessary to customize how the objects are created.

sacarro replied on Monday, September 15, 2008

Great I will test that out. Thanks for the quick response and solution. Also good to hear Miguel is still actively giving you suggestions. :)

Copyright (c) Marimer LLC