I need to implement a WCF service that conforms to the specs set forth by Phase II CORE 270 Connectivity Rule.
I generated the service using svcutil.exe and the supplied wsdl.
Given that we had chosen to handle security through username/password over SSL and the requirement for SOAP 1.2 addressing, I configured the service as a
customBinding:
<customBinding>
<binding name="ServiceBinding">
<security
authenticationMode="UserNameOverTransport"
messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10">
</security>
<textMessageEncoding messageVersion="Soap12" />
<httpsTransport />
</binding>
</customBinding>
The WSDL produced matches that of the WSDL provided by the spec. Using a supplied soap message:
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<soapenv:Header>
<wsse:Security
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="true">
<wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wsswssecurity-utility-1.0.xsd" wsu:Id="UsernameToken-21621663">
<wsse:Username>bob</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-usernametoken-profile-1.0#PasswordText">bobPW</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<ns1:COREEnvelopeRealTimeRequest
xmlns:ns1="http://www.caqh.org/SOAP/WSDL/CORERule2.2.0.xsd">
<PayloadType> X12_270_Request_005010X279A1004010X092A1</PayloadType>
<ProcessingMode>RealTime</ProcessingMode>
<PayloadID>f81d4fae-7dec-11d0-a765-00a0c91e6bf6</PayloadID>
<TimeStamp>2007-08-30T10:20:34Z</TimeStamp>
<SenderID>HospitalA</SenderID>
<ReceiverID>PayerB</ReceiverID>
<CORERuleVersion>2.2.0</CORERuleVersion>
<Payload><![CDATA[ISA*00* *00* *ZZ*NEHEN780 *ZZ*NEHEN003 ...IEA*1*000000031]]></Payload>
</ns1:COREEnvelopeRealTimeRequest>
</soapenv:Body>
</soapenv:Envelope>
and SoapUI, I am receiving a
System.ServiceModel.Security.MessageSecurityException, System.ServiceModel,
Security processor was unable to find a security header in the message. This might be because the message is an unsecured fault or because there is a binding mismatch between the communicating parties. This can occur if the service is configured for security and the client is not using security.
It would seem that the service does not understand the wsse namespace prefix as if I flip the namespace prefix to o the service does not have an issue with the request.
EDIT
I cannot seem to find the mismatch in the binding or an issue with their message indicating I am chasing up the wrong tree. Any other potential leads would be helpful. Is there a way to make a custom binding with SOAP 1.2 addressing inter-operable with the provided SOAP message?
Related
I'm trying to add WS-Security to an existing service I have, where said service is accessed over TLS, and I've mostly succeeded in testing it with SoapUI.
However I'm having a problem with the response coming back; even though the response looks complete, SoapUI reports:
ERROR:org.apache.ws.security.WSSecurityException: An invalid security token was provided (Bad TokenType "")
org.apache.ws.security.WSSecurityException: An invalid security token was provided (Bad TokenType "")
at org.apache.ws.security.str.BSPEnforcer.checkEncryptedKeyBSPCompliance(BSPEnforcer.java:113)
at org.apache.ws.security.str.SecurityTokenRefSTRParser.processPreviousResult(SecurityTokenRefSTRParser.java:313)
at org.apache.ws.security.str.SecurityTokenRefSTRParser.parseSecurityTokenReference(SecurityTokenRefSTRParser.java:101)
at org.apache.ws.security.processor.ReferenceListProcessor.decryptDataRefEmbedded(ReferenceListProcessor.java:169)
at org.apache.ws.security.processor.ReferenceListProcessor.handleReferenceList(ReferenceListProcessor.java:104)
at org.apache.ws.security.processor.ReferenceListProcessor.handleToken(ReferenceListProcessor.java:64)
at org.apache.ws.security.WSSecurityEngine.processSecurityHeader(WSSecurityEngine.java:402)
From what I'm reading, this is due to a missing TokenType attribute on the SecurityTokenReference element in the reply, and this is a condition of complying with the Basic Security Profile.
The question is - how do I get this attribute populated in WCF? I've not found any clear information on this.
The encrypted key section in the SOAP response from the WCF service looks like this:
<e:EncryptedKey Id="_0" xmlns:e="http://www.w3.org/2001/04/xmlenc#">
<e:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p">
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" xmlns="http://www.w3.org/2000/09/xmldsig#"/>
</e:EncryptionMethod>
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<o:SecurityTokenReference>
<o:KeyIdentifier ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509SubjectKeyIdentifier" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">K6Ag94AG3hQuQ+rqQcBvb88Vl+Y=</o:KeyIdentifier>
</o:SecurityTokenReference>
</KeyInfo>
<e:CipherData>
<e:CipherValue>FQ58hAfisez2D8J9A49xFRQjfTSFhrWP9wJDnWq0MctAyLhoAynzu3/Z0jYK91uE4DVCgkFo9QGH6O/kR1icQxkpv/xb5gcB1mJTbIpbCOzw6ZtMEfbY0r9ML2fDcChGFPM/nh70Daqi4P9IO8dIZ5EAUcERvDMFvj4fhwwVycSNFUX40/8ywQALQksPb+1j2B3pzHntcyb6CJ0qD10xjbyyQoT0BgR/HeDQEJDQNvx41eqoDSy2/ImkNNfFCXQ47/k1sN48tWur6GEzDuwUBbiAJxVrCgzc6a7F9CrhWiE6DAublBzM8/EBKP5UD5p2WTcjDQxI4cBhqRwIGYcfhQ==</e:CipherValue>
</e:CipherData>
</e:EncryptedKey>
My WCF bindings look like this:
<customBinding>
<binding name="NewBinding0">
<security
authenticationMode="MutualCertificate"
allowSerializedSigningTokenOnReply="true"
messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"
securityHeaderLayout="Lax"
requireSignatureConfirmation="false"
messageProtectionOrder="EncryptBeforeSign"
includeTimestamp="false"
>
<localServiceSettings detectReplays="false" />
</security>
<textMessageEncoding messageVersion="Soap11" />
<httpsTransport />
</binding>
</customBinding>
As an afterthought, is BSP strictly required to be a "good" message? I can't see any way to switch BSP checking off in SoapUI, but given WCF doesn't apply it I assume it is acceptable? Ultimately, consumers of the service may be Java, may be .NET, may be something else, so I'm happy to drop BSP support in the name of wider compatibility if BSP can be disabled. If this does seem an acceptable path, then rather than .NET attempting to conform to BSP, how do I switch BSP processing off in SoapUI for testing? (That said, if enabling BSP in .NET is straight forward by tweaking the binding, I'm happy to persue that).
I have a WCF service that has the following requirements:
Sent over SSL (HTTPS Transport)
Reliable Messaging On
WS-* message security using a X.509 certificate.
Replay Detection On
Here is the binding that I have:
<customBinding>
<binding name="replayDetectionBinding">
<reliableSession />
<security authenticationMode="SecureConversation">
<secureConversationBootstrap authenticationMode="CertificateOverTransport"
protectTokens="true">
<issuedTokenParameters keyType="AsymmetricKey" />
</secureConversationBootstrap>
<localServiceSettings maxClockSkew="00:01:00"
replayWindow="00:01:00" />
</security>
<textMessageEncoding />
<httpsTransport maxReceivedMessageSize="5242880" maxBufferSize="5242880" />
</binding>
</customBinding>
The service is hosted in IIS and I have a test client to make a request to the service. I have Fiddler up and running to catch all messages coming to and from the test client and the WCF service.
Everything is working, including the replay detection outside of the replay window. However, what I need is to have the replay detection use the nonce cache so that an identical message is rejected no matter what (as long as that message signature is in the nonce cache). This part is not happening.
I send a message using the test client, it is received by the WCF service and a response is returned, I do not close the connection. I then use Fiddler to reissue/replay the message that was sent. In this case, it is accepted by fiddler - even if I issue it from another machine.
I've done so much searching and have read just about everything I can find, but cannot get this to work.
Does anyone know how to enable the nonce cache in this case or do you have to code your own?
I have one third party SOAP client that is capable of communicating with old ASMX webservices.
The problem is with a WCF services.
My WCF service receives messages from this client without problems, but the client does not like my WCF responses.
My test WCF service sends out the following response:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<testResponse xmlns="http://www.tempuri.org">
<testResult>randomStringData</testResult>
</testResponse>
</s:Body>
</s:Envelope>
But the old SOAP Client expects this kind of response(ASMX service):
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<testResponse xmlns="http://tempuri.org/">
<testResult>randomStringData</testResult>
</testResponse>
</soap:Body>
</soap:Envelope>
I have no control over the client.
Is there a way i could configure my WCF to send out exactly the same message as my ASMX service does?
My WCF Service is using the following binding:
<customBinding>
<binding name="soap11">
<textMessageEncoding messageVersion="Soap11" writeEncoding="utf-8"></textMessageEncoding>
<httpTransport></httpTransport>
</binding>
</customBinding>
I managed to solve the prefix problem with custom message inspector and with BeforeSendReply method.
http://msdn.microsoft.com/en-us/library/system.servicemodel.dispatcher.idispatchmessageinspector.beforesendreply.aspx
P.S Another great method is AfterReceiveRequest for all kind of message tweaking magic!
I'm building a WCF web service that requires interop with non-WCF clients (in fact, there will be no WCF clients).
I've already written a WSDL using SOAP 1.2 (as per this example). I've validated the WSDL and have used this file (not the WSDL generated by WCF, which is superficially different) to create a soapUI test project.
I have a requirement that the web service will support SOAP 1.2, so I can't just fall back to SOAP 1.1 (which worked just fine in an early prototype).
I've used WSCF.blue to generate my WCF service, interface, and data contract classes. Everything compiles nicely and the endpoint is exposed if I hit the WCF service in my browser. All seems well with the world.
When I try to call a method from soapUi I get the following response from the server (as visible from soapUI):
HTTP/1.1 415 Cannot process the message because the content type
'application/soap+xml;charset=UTF-8;action="http://tempuri.org/FetchMyThing"'
was not the expected type 'text/xml; charset=utf-8'.
Server: Microsoft-IIS/7.5
X-Powered-By: ASP.NET
Date: Mon, 30 Apr 2012 08:15:29 GMT
Content-Length: 0
(Actual method names and namespaces have been manually changed for the purposes of this question. Any typos in namespace are not errors in my code - just an oversight in typing up this question)
I know that SOAP 1.1 specifies that the content type must be text/xml. SOAP 1.2 requires application/soap+xml.
My raw request (as per soapUI):
POST http://localhost/MyWs.svc HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: application/soap+xml;charset=UTF-8;action="http://tempuri.org/FetchMyThing"
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:ns="http://tempuri.org">
<soap:Header/>
<soap:Body>
<ns:fetchMyThingRequest attribute1="1" attribute2="10">
</ns:fetchMyThingRequest>
</soap:Body>
</soap:Envelope>
From this response, it tells me that my request is properly formed - it's a SOAP 1.2 request with the correct content type. My WCF service, however, does not expect this content type, which I assume means I have not configured it correctly and it still thinks it's a SOAP 1.1 web service.
Minimal Web.config, as per this blog post:
<system.serviceModel>
<services>
<service name="MyNamespace.MyPort">
<endpoint address="" binding="customBinding" bindingConfiguration="httpSoap12" contract="IWsPort12" />
</service>
</services>
<bindings>
<customBinding>
<binding name="httpSoap12">
<textMessageEncoding messageVersion="Soap12" />
<httpTransport />
</binding>
</customBinding>
</bindings>
</system.serviceModel>
A snippet of the service contract:
[ServiceContract(Namespace = "http://tempuri.org")]
public interface IWsPort
{
[OperationContract(Action = "http://tempuri.org/FetchMyThing")]
[FaultContract(typeof(WsFault), Action = "http://tempuri.org/FetchMyThing", Name = "fetchMyThingFault")]
[XmlSerializerFormat(SupportFaults = true)]
FetchMyThingResponse FetchMyThing(FetchMyThingRequest request);
}
I enabled service tracing for my WCF service and see the following exception that seems to confirm my hypothesis:
Activity: Listen at 'http://mycomputer/MyWs.svc
<Exception>
<ExceptionType>System.ServiceModel.ProtocolException, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType>
<Message>Content Type application/soap+xml;charset=UTF-8;action="http://tempuri.org/FetchMyThing" was sent to a service expecting text/xml; charset=utf-8. The client and service bindings may be mismatched.
</Message>
(erroneous detail snipped)
</Exception>
So, my contract and service bindings are probably mismatched, if this message is to believed, but from what I understand of WCF my configuration (or at least the intent behind it) is correct.
Does anyone have any ideas as to what's wrong with my configuration?
The only thing I can think with it is that because you've not specified a binding in a lot of detail, and its using HTTP (as per this: "Listen at 'http://mycomputer/MyWs.svc'") then is it using the default (i.e. basicHttpBinding) for this, which is creating the mismatch?
I had the same issue when I had multiple bindings on my service. When I removed all bindings and only left one unnamed binding in place, the error message disappeared.
Please check this link How to: Configure WCF Service to Interoperate with ASP.NET Web Service Clients
.
To configure a Windows Communication Foundation (WCF) service endpoint
to be interoperable with ASP.NET Web service clients, use the
System.ServiceModel.BasicHttpBinding type as the binding type for your
service endpoint.
Also, defining two endpoints you can use HTTP and HTTPS versions of the same service
I am trying to use a WCF client to call a third party web service.
The web Service usses username token authentication WSS-Security 1.0 Soap Message Security
Here is a sample soap authentication header for what the web service expects
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<wsse:Security soap:mustUnderstand="1">
<wsse:UsernameToken namespaces>
<wsse:Username>username</wsse:Username>
<wsse:Password Type="type info">password</wsse:Password>
<wsse:Nonce>nonce</wsse:Nonce>
<wsu:Created>date created</wsu:Created>
</wsse:UsernameToken>
<wsse:Security>
</soap:Header>
<soap:Body>
<WebServiceMethodName xmlns="Web Service Namespace" />
I configured the client to the following way
<basicHttpBinding>
<binding name="Binding1">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Basic"/>
</security>
</basicHttpBinding>
but recieved an error that stating that the nonce and datecreated attributes were missing in the header. Does anyone know how to configure a WCF client to work with
WSS-Security 1.0 Soap Message Security username token authentication?
I had the same problem. Instead of the custom token serlializer I used a MessageInspector to add the correct UsernameToken in the BeforeSendRequest method. I then used a custom behavior to apply the fix.
The entire process is documented (with a demo project) in my blog post Supporting the WS-I Basic Profile Password Digest in a WCF client proxy. Alternatively, you can just read the PDF.
If you want to follow my progress through to the solution, you'll find it on StackOverflow titled, "Error in WCF client consuming Axis 2 web service with WS-Security UsernameToken PasswordDigest authentication scheme":
Been looking at the same problem and my findings are that unfortunately WCF doesn't support Nonce values.
If you want to send username and password (timestamp is included by default) change the config to
<basicHttpBinding>
<binding name="BasicHTTP">
<!-- UsernameToken over Transport Security -->
<security mode="TransportWithMessageCredential">
<message clientCredentialType ="UserName" />
</security>
</binding>
</basicHttpBinding>
Also be aware that it appears to be a defect (at least different interpretation of the standards) with regards to the UserNameToken when exchanged between WCF and WSS4J see http://social.msdn.microsoft.com/Forums/en/wcf/thread/6bc1b0e4-424b-4e2a-909c-815095be631f
WSSConfig.getDefaultWSConfig().setAllowNamespaceQualifiedPasswordTypes(true); might be a workaround on the WSS4J side.
UPDATE: On the WCF side you can get around the problem by implementing a CustomCredential and CustomTokenSerializer ref last post at
http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/4df3354f-0627-42d9-b5fb-6e880b60f8ee
Dagfinn