WSSE WCF client with Java server "Cannot find a token authenticator for the 'System.IdentityModel.Tokens.UserNameSecurityToken' token type."

StackOverflow https://stackoverflow.com/questions/18652795

  •  27-06-2022
  •  | 
  •  

質問

I am trying to integrate with a Java service from WCF. The server requires an OASIS WSSE security header for username + password authentication. Transport security is provided by SSL on the server side (no client certificate for mutual authentication). The request is working, but WCF falls over when processing the response...

Using Fiddler2, I see a valid response coming back from the server without any issues, but it looks like WCF chokes on the wsse:UsernameToken which is echoed in the response from the server.

Is there any way to ignore client-side authentication on the token coming back in the server's response? I imagine I need to have a dummy authenticator and somehow attach it to the client's response processing, but I am not sure where to hook into that logic.

I do not want to use WSE 3.0 and all the client setup is in code (no external assemblies or config files).

Code

private static IEndPointClient NewProxy(string userName, string password)
{
    //Basic SOAP over TLS/SSL with WSSE header for authentication
    var baseBinding = new BasicHttpBinding(BasicHttpSecurityMode.TransportWithMessageCredential);

    //Strip the TimeStamp element from the WSSE header - server does not expect it
    var elements = baseBinding.CreateBindingElements();
    var securityElem = elements.Find<SecurityBindingElement>();
    securityElem.IncludeTimestamp = false;

    var binding = new CustomBinding(elements);
    var address = new EndpointAddress(UATSERVER);    

    var svc = new EndPointClient(binding, address);    
    svc.ClientCredentials.UserName.UserName = userName;
    svc.ClientCredentials.UserName.Password = password;
}

MessageSecurityException message and stack trace

Cannot find a token authenticator for the 'System.IdentityModel.Tokens.UserNameSecurityToken' token type. Tokens of that type cannot be accepted according to current security settings.

Server stack trace: 
   at System.ServiceModel.Security.ReceiveSecurityHeader.ReadToken(XmlReader reader, SecurityTokenResolver tokenResolver, IList`1 allowedTokenAuthenticators, SecurityTokenAuthenticator& usedTokenAuthenticator)
   at System.ServiceModel.Security.ReceiveSecurityHeader.ReadToken(XmlDictionaryReader reader, Int32 position, Byte[] decryptedBuffer, SecurityToken encryptionToken, String idInEncryptedForm, TimeSpan timeout)
   at System.ServiceModel.Security.ReceiveSecurityHeader.ExecuteFullPass(XmlDictionaryReader reader)
   at System.ServiceModel.Security.StrictModeSecurityHeaderElementInferenceEngine.ExecuteProcessingPasses(ReceiveSecurityHeader securityHeader, XmlDictionaryReader reader)
   at System.ServiceModel.Security.ReceiveSecurityHeader.Process(TimeSpan timeout, ChannelBinding channelBinding, ExtendedProtectionPolicy extendedProtectionPolicy)
   at System.ServiceModel.Security.TransportSecurityProtocol.VerifyIncomingMessageCore(Message& message, TimeSpan timeout)
   at System.ServiceModel.Security.TransportSecurityProtocol.VerifyIncomingMessage(Message& message, TimeSpan timeout)
   at System.ServiceModel.Security.SecurityProtocol.VerifyIncomingMessage(Message& message, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
   at System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.ProcessReply(Message reply, SecurityProtocolCorrelationState correlationState, TimeSpan timeout)
   at System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs)
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
役に立ちましたか?

解決

You have two options:

  1. Implement a custom message encoder in which you strip out the username from the response
  2. Dismiss any security setting from WCF all together (e.g. BasicHttpSecurityMode.None) and push the outgoing user/pass SOAP headers to the message by yourself (they are very simple xml elements) via a message inspector (easiest) or encoder or a custom header.
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top