Search code examples
wcfwcf-securityws-security

stop WCF from caching / re-using security tokens (SecurityContextToken)


I am using WCF Message level security with the following wsHttpBinding

  <security mode="Message">
    <message clientCredentialType="Windows" establishSecurityContext="false" />
  </security>
  • Each time i call the service is a separate operation, and there is no need to keep any session state.

  • I am running into a problem with load balancer, because WCF keeps re-using security tokens, so if the first call goes to NodeA, it creates a security token which is re-used. If that token is passed to NodeB tripping up MessageSecurityException

  • Seems like microsofts answer to this is to use sticky sessions, which is something we explored but it does not make sense in our setup

Is there a way to simply force WCF to create a new Security Token on every call? (while using Message level security with Windows credential type?

update

i setup trace on client / server and i can i see that the token is cached for 24 hrs.

<ServiceToken>
<SessionTokenType>System.ServiceModel.Security.Tokens.BufferedGenericXmlSecurityToken</SessionTokenType>
<ValidFrom>2013-03-23T21:21:32.569Z</ValidFrom>
<ValidTo>2013-03-24T07:21:32.569Z</ValidTo>
<InternalTokenReference>LocalIdKeyIdentifierClause(LocalId = 'uuid-291b4a38-af17-4832-bc7a-6fb65dcc3c3c-18', Owner = 'System.ServiceModel.Security.Tokens.SecurityContextSecurityToken')</InternalTokenReference>

The IssuanceTokenProvider used the cached service token.

i've tried disabling token cashing using the following:

IssuedTokenClientCredential itcc = service.ClientCredentials.IssuedToken;
itcc.CacheIssuedTokens = false;
itcc.LocalIssuerAddress = new EndpointAddress("http://localhost:####/myservice");
itcc.LocalIssuerBinding = new WSHttpBinding("my_wsHttp_bindingConfig");
itcc.MaxIssuedTokenCachingTime = new TimeSpan(0,0,0);

but looking at the wcf trace, it appears that above doesn't affect the negotiation at all.

i am still seeing that cached tokens are used.


Solution

  • after a lot of research, and pouring through the WCF trace, and contacting Microsoft, i got to the bottom of this problem.

    1. when using message level security, WCF issues Security Context Token based authentication (SCT)

    2. this type of authentication simply relies on sticky session, no way around it.

    3. there is a setting which is supposed to disable it EstablishSecurityContext=false, but this does not work. after setting this i can see in a trace that SCT's are being used just as before (and i got someone at Microsoft to confirm i wasn't doing anything unusual here). There might be another dependency on this setting, but a senior MS engineer didn't know why this setting wasn't working either.

    4. this leaves a few options

      a. use "one shot" calls with Kerberos - i did not explore this because turning on kerberos in my scenario would have been a bigger headache

      b. use a custom binding with NTLM based auth - i tried this, but SCT's were still being used, so it didn't work for me

      c. use federated security with custom Token issuing service. This gives a finer control over how tokens are issued, but with unnecessary (in my case) overhead of having to manage this

      d. use basic http binding with TransportCredentialOnly security mode. this is nice because it stops SCT negotiation, while still passing a windows credential.

    4.d was the easiest for me because i didn't have to do a lot of changes besides config. i am giving up wshttpbinding features, but so far this is ok because this conversation is happening within a trusted network.