Sunday, June 10, 2012

12 common wcf interop confusions

@YaronNaveh

I get mails almost on a daily basis from people asking me how to build a Wcf client to consume a service of framework X (usually axis or wsit but others as well). After getting hundreds of these mails in the recent years I conclude that there is a single most common setting which most people need. There are also common confusions that a lot of people stumble on in their first try. In this post I will present the common setting, and what can (and will) go wrong.

The mails I get usually start with this soap sample which people want wcf to send:


Optionally ssl is also used.

The wcf setting required here is a custom binding with an authentication mode of "mutualCertificate":


(where https may be used instead of http)

Confusion 1: A wrong soap version by you can cause the server to return different kinds of exceptions. Make sure the "messageVersion" property on the textEncodingElement fits your needs. In particular if no ws-addressing headers are used (To, ReplyTo, MessageID and Action) then use "Soap11" (as above) or "Soap12" without any ws-addressing version.

Confusion 2: The proxy may throw this exception:

The client certificate is not provided. Specify a client certificate in ClientCredentials.

That's an easy one, you must confiugure a client certificate which is pretty basic for a signing scenario. You can do it from code or config. Here is the config version:


Confusion 3: You still get the same error after you have defined the certificate. In this case make sure you have configured the endpoint to use the behavior:


Confusion 4: When I use mutualCertificate authentication mode I define my client certificate. I do not have a server certificate to define. My proxy is not sending anything and throws this error:

The service certificate is not provided for target 'http://localhost/MyWebServices/Services/SimpleService.asmx'. Specify a service certificate in ClientCredentials.

The issue is that mutualCertificate always requires you to define a server certificate. In some cases you may not need it. In such cases it is ok to define some dummy certificate as the server certificate, even can be the same certificate you use for the client:


Of course you may also do so from code.

Confusion 5: You may get this error:

"The X.509 certificate CN=WSE2QuickStartServer chain building failed. The certificate that was used has a trust chain that cannot be verified. Replace the certificate or change the certificateValidationMode. A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider.\r\n"

This typically mean the server certificate you have defined is not trusted by your machine. In the case that you have defined a dummy server certificate (see confusion 3) or in other cases - at your risk and for testing purpose only - you can turn off this validation by setting certificateValidationMode to None.


Confusion 6: I am getting a good response from the server but the proxy throws this exception:

The incoming message was signed with a token which was different from what used to encrypt the body. This was not expected.


Congratulations, turns out you need to define a real server certificate anyway (so confusion 2 does not apply). You should get it from the service author. But if you don't there a nice trick to infer the certificate by extracting the value of the binary security token from the message and saving it to disk (in binary form) as alluded here.


Confusion 7: I am getting a good response from the server but the proxy throws this exception:

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.

This means the service is not signing the response even though you sent a signed request. In .Net 4+ you can turn off the secured response requirement by toggling the security channel in your custom binding:


Confusion 8: When I use mutualCertificate I see my proxy sends a message in a very different from what I need. In particular there is no signature but only encryption, something like this:


What you need to know is that by default messages will be signed AND encrypted, and moreover the encryption will also encrypt the signature and "hide" it from your eyes. The solution is to set the correct protection level on your contract:


btw while interoperating with some java stacks you will know you are in confusion #8 if you get this error:

General security error (WSSecurityEngine: No crypto property file supplied for decryption)

Confusion 9: After applying the mitigation to confusion 7 the outgoing message is still not in the desired format. In particular the message is not signed by the binary token by a derived token, and there is a primary and a secondary signature instead of just one:



For all things interop wssecurity10 is your friend and wssecurity11 is the enemy. keep your friends close! Make sure the messageSecurityVersion attribute has a value that starts with wssecurity10:


Confusion 10: You get this error :

Identity check failed for outgoing message. The expected DNS identity of the remote endpoint was 'localhost' but the remote endpoint provided DNS claim 'WSE2QuickStartServer'. If this is a legitimate remote endpoint, you can fix the problem by explicitly specifying DNS identity 'WSE2QuickStartServer' as the Identity property of EndpointAddress when creating channel proxy.

You fell for the oldest trick in the book! Just do exactly what the error tells you to do . Yes, it's ok...

Confusion 11: You get a good response from the server but the proxy throws this error:

No Timestamp is available in security header to do replay detection

or this one:

The security header element ‘timestamp’ with ‘Timestamp-xxxx’ id must be signed.

These may happen when you send to the server a signed timestamp so wcf expects to get one back AND to have it signed. So either you do not get one back or it is not signed. For start try to set the includeTimestamp property on the "security" binding element to false. But this will not work if the server actually requires a timestamp. If it requires one but unsigned then write a custom encoder to you proxy and manually generate and push the timestamp header to the request. If the server requires a signed timestamp then your only hope is to set allow unsecured response to true (.net 4 only):



AND to strip out ANY remains of the "security" tag from the response (not just the timestamp) using a custom encoder. If WCF will see the security tag then it will be very defensive and try to validate it. Of course if the security tag which you removed contains some signature this means you will not be able to validate it, which is a shame. I'm not familiar with any better workaround at this moment, so I'm investigating a few directions.

Confusion 12: Ssl is used, and you try certificateOverTransport instead of mutualCertificate authentication mode on your custom binding. You may get away with the request, since it is similar, but once the response come back you may experience:

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

What's going on here? certificateOverTransport assumes the client authenticates with a message level certificate, but the server authenticates with its transport ssl certificate. However a more common use case is that the server also authenticates with a message level certificate, in addition to its transport one. You could identify such scenario by seeing a signature element in the server response. This means you need a mutualCertificate authentication mode together with an https transport binding element:


Summary
When Wcf consumes third party services, the most common authenticationMode would be "mutualCertifiate". Make sure you tried all combinations of this setting before trying other settings. Of course if you are in a situation where mutualCertificate clearly does not apply (e.g. username authentication) then this is not relevant for you. But even when usernames are used they may still be in combination with a client certificate, in which case it would still make sense to SecurityBindingElement.CreateMutualCertificateBindingElement() for bootstrap and add the username as a supporting token.

@YaronNaveh

What's next? get this blog rss updates or register for mail updates!

78 comments:

Mitesh Patel said...
This comment has been removed by the author.
Yaron Naveh (MVP) said...

Hi Mitesh

Can you send me the soap you send and response you get?

Mitesh Patel said...

Hello Yaron,

I have tried with given configuration but getting "unsigned element body found". I have trace the output request but only one Reference element is generated instead of two. Also Uri in this reference element is not also proper.

Please help me !

Thanks
Mitesh

Yaron Naveh (MVP) said...

check out confusion 8 - you need ProtectionLevel.SignOnly. Maybe now it is None.

Mitesh Patel said...

Hello Yaron,

I could not have a control on third party service side. But from client side I have tried out using custom binding. But the same error still I am getting.

Another thing, when I used Microsoft Service Trace Viewer for tracing, I am getting "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." error. For this I have tried with Confusion#8: enableUnsecuredResponse="true" but still same error.

This one is really strange !!!

Thanks
Mitesh

Mitesh Patel said...
This comment has been removed by the author.
Yaron Naveh (MVP) said...

the error you got makes a lot of sense - the server returns an unsecured soap fault (as seen in the sample you sent to my mail).
the fault specifies that the problem is that your request does not encrypt the soap body. this is not related to the binding you use - it is related to the ProtectionLevel in reference.cs. See confusion 8 for more details.

cvraghu said...

I've a soap client accessing a routing service by passing in a certificate. I always receive "The client certificate is not provided" error. How do we pass certificate from a soap client. I've posted in msdn forum too.

http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/b2be687f-cd5d-4a70-aa6e-49ff3e3d4391

Mitesh Patel said...

Hello Yaron,

I tried with confusion 8. But same error "unsigned element body found".

Thanks
Mitesh

Yaron Naveh (MVP) said...

cvraghu - Yi-Lun had already answered you in the msdn forum

Yaron Naveh (MVP) said...

Mitesh - please send me again how your request looks like. if the body is still not signed can you send me a sample cs project so I can see the proxy and the request?

Mitesh Patel said...

Hello Yaron,

I have tried with following and now able to get response as almost same as required.

1. Set Protectionlevel =Sign in reference.cs
2. Use following custom binding.

HttpsTransportBindingElement httpsBindingElement = new HttpsTransportBindingElement();
httpsBindingElement.AllowCookies = false;
httpsBindingElement.BypassProxyOnLocal = false;
httpsBindingElement.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
httpsBindingElement.MaxBufferPoolSize = 524288;
httpsBindingElement.MaxBufferSize = 65536;
httpsBindingElement.MaxReceivedMessageSize = 65536;
httpsBindingElement.RequireClientCertificate = true;
httpsBindingElement.UseDefaultWebProxy = true;

System.ServiceModel.Channels.AsymmetricSecurityBindingElement asbe = new System.ServiceModel.Channels.AsymmetricSecurityBindingElement();
asbe.MessageSecurityVersion = MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11;
asbe.InitiatorTokenParameters = new System.ServiceModel.Security.Tokens.X509SecurityTokenParameters();
asbe.RecipientTokenParameters = new System.ServiceModel.Security.Tokens.X509SecurityTokenParameters();
asbe.SecurityHeaderLayout = SecurityHeaderLayout.Strict;

asbe.IncludeTimestamp = true;
asbe.SetKeyDerivation(false);

CustomBinding myBinding = new CustomBinding();

myBinding.Elements.Add(asbe);

myBinding.Elements.Add(new TextMessageEncodingBindingElement(MessageVersion.Soap11, System.Text.Encoding.UTF8));

myBinding.Elements.Add(httpsBindingElement);

But now getting "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." error.

So your solution#8 works here. Great !! Thanks a lot for it.

Now I am getting Timestamp, UsernameToken, Assertion, BinarySecurityToken in my response.

So could you please help me how to deal with UserNameSecurityToken error.

I am sending you the Response File.

Thanks Again
Mitesh

Yaron Naveh (MVP) said...

according to the error the server does not want a username token, but you send one. to figure it out please send me the server config or - better - a sample working request

Unknown said...

I need to access a client with this header...





MedTrak_Dev
uncJUN132012
Hozef94FFwOhuiF5QixaMQ==
2012-08-21T13:26:03.642Z




I have been trying all sorts of things on different websites and I can't figure out how on earth to do it?

Yaron Naveh (MVP) said...

Unknown - please send me your xml, it does not appear correctly in comments

Unknown said...




----------
----------
Hozef94FFwOhuiF5QixaMQ==
2012-08-21T13:26:03.642Z



Hey there. thought I had it in my last post. How do you put code in your comments. It strips out everything except some random stuff...

Yaron Naveh (MVP) said...

mail it to me - I don't think you can paste xml here

Unknown said...

sent it to you.

KeepingItSimple said...

Yaron,

Thank you very much for summarizing most of the usual confusions with WCF interop.

In my case with a MutualCertificate and assigned Certificates with UsernameToken, we are running into exception message with strange Error Codes 3001.

Any idea what these might be ?

Thank you,

KRK

Yaron Naveh (MVP) said...

KeepingItSimple - is there anything to the error message except the number? IF you turn on logging, does the error happens after some messages are send or before all?

Dhaval Heruwala said...

HI Yaron,

I am facing the same issue as Mitesh where my request is failing with error "unsigned element s:body found". I tried almost all the options you have suggested for custombinding but none of them are working. I see you are the only expert who can deal with such issues. I know its all magic of Client's app.config. Could you please advise what settings should I use in app.config? I have posted working SOAP UI request at
http://stackoverflow.com/questions/13076456/how-to-consume-java-webservice-from-net-and-wcf

Thanks,
Dhaval Heruwala

Yaron Naveh (MVP) said...

Hi Dhaval

I answered you in SO

toddmoon said...

Regarding "Confusion 7: I am getting a good response from the server but the proxy throws this exception:"

You said, "turn off the secured response requirement by toggling the security channel in your custom binding."

I'm using your ClearUsernameBinding, and when I added security node to the binding and I run the app I get "Unrecognized element 'security'" when I instantiate the client.

Is this node not supported by your ClearUsernameBinding?

Yaron Naveh (MVP) said...

Hi toddmoon

this setting should not be relevant in case CUB is used. CUB assumes already the response is not secured and should not throw an exception.

toddmoon said...

Thanks for the reply, Yaron. Maybe I can give you more details. I'm using a service reference to an Oracle EBS web service in VS 2012. Our test server is not running SSL, but the service requires UserName authentication, so I'm using the CUB.

I'm certain my app.config file is setup properly. It looks very similar to the example in the CUB solution.

I'm using Fiddler2 to watch my http traffic, and I get a 200 response from the server with a valid SOAP message for my query yet I get the exception, "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."

Are there other reasons for this error?

Yaron Naveh (MVP) said...

Hi toddmoon

This is a surprising behavior. Try to change the CUB code. In ClearUsernameBinding.cs in the function CreateBindingElements() you can configure security.EnableUnsecuredResponse = true.

An alternative is to remove CUB (or any other security configuration) all together and just push the user/pass headers in a custom message inspector.

toddmoon said...

Thanks! That fixed it. Specifically:

var sec = SecurityBindingElement.CreateUserNameOverTransportBindingElement();
sec.EnableUnsecuredResponse = true;
res.Add(sec);

Unknown said...

Hi Yaron,

Thanks for collating all such findings in one post, really appreciate.
I am writing this comment to better understand a behavior happening in my service. I am using custom binding with following binding/behavior config on a service with ProtectionLevel = Sign:
























Now the requests from the client work fine and both request and response are signed. However, the same set of configuration and endpoint works with a test client with following config:
























I am not able to understand when the client config is not configured to use the actual client cert ('ClientCert123') for signing requests, instead it's using the service cert ('ServiceCert456') for same how is the service able to verify the signature and process the request? Shouldn't the service fail on requst verification as the client cert wasnt used to sign it?

Yaron Naveh (MVP) said...

Hi

Xml does not appear good in comments, send me this in mail

Unknown said...

Thanks Yaron. Just emailed you a question on gmail.

Cp2013 said...

Hi Yaron,

Thank you for the detailed instructions ...
I'm following your multiple posts from your blog, msdn etc
And finally I'm pretty close to what I need to connect WCF to Java.

Java libraries by default signing only the soap body and the service i'm trying to connect is enforcing that requirement.

I've added ProtectionLevel = ProtectionLevel.Sign in ServiceContractAttribute and used authenticationMode="MutualCertificate", and now my program signs the soapy body and header.

This is my custom binding settings:




And my request (client to server) looks like this (captured from system.diagnostics log) :









Io49spWVugH8MIf/bxRdsDWu/+5o64YckOseT2SKl+s=






HpdlziZeCi2mt75K8l5bxG26aIloIu9Qf02q6mHxvSE=






/Ha5dHhAjKbd1Bo5ytgeqW283FLEFtfuoQZLnXJtzjo=


JQPcYF7Aa/XwK6sKSdu+hsyM5gvH4/JvRFggzdGpy96uH1KcHO/nyRsw0Ml5sMlr7Z7AgnF4iFoksJcKGCZjZJRAPtM0e1nz5iYWW9C5Njd8gXn0iKkvzdeFQriNwDQRVXHUTJs7tXNDLgglHwFPYle80NVgpXN/PG2zQEc22XwTGw8iEOUkj/R9aDGb+tOkYF2MMV1pdOLH9FSSpQehVjRbHtDL2FlKSR4R9X1FHwsHA2+vAQzlBw6kacQLUkx49sS7Zfq7fXx1kpqRN2JqFZnzOwI3WCiahjWa8XCMTm0VzQbT+J+7vNTHlAoQXsf0/NEHqzaojHKiipKr/FYeog==







But getting FailedCheck : failure in security check from Server.
And on follow up they informed me that it requires only , which is signed Soap body reference.

Is there any way I can avoid WCF to signing the "Timestamp" (URI="#uuid-d1c26717-6465-417f-9c45-5cfbe9edd779-1") and a header node (URI="#_2") ?

I'm trying to find out if it can be done using custom binding settings in app.config, not successful yet.
Thought of checking with you if at all possible to do this by a correct custom binding ?
If not an option at all, Do you think I can do it by modifying request some way in my C# code ? (I tried to see the request by implementing IClientMessageInspector - that gives me request before WCF actually signing the message)

I really appreciate if you can suggest some way to make this work in WCF.

Thanks,
--Cp

Yaron Naveh (MVP) said...

Hi CP - the XML does not appear good in comments, please send me in mail

Asad Ahmed said...

How can I specify a minimum byte size value that should be mtom optimized by wcf programtically or by config means. The purpose is to control, for instance , only byte size greater than 3000 should be mtom optimzed by wcf when sending an mtom request. Any thoughts?

Yaron Naveh (MVP) said...

Hi Asad - check my answer to you in SO http://stackoverflow.com/questions/19599286/need-to-avoid-digital-signature-public-certificate-binarysecurityelement-from-be/19613189#19613189

Cp2013 said...

Thank you Yaron for the post and reply to emails. Yes I got this working.

Syed said...

am trying the same thing but getting request soap below in my inspection .
whats wrong?




http://localhost:35202/schemas/customs/service/ManifestDeclaration/ManifestDeclarationPortType/ManifestDeclarationRequest
bd29e195-7297-4f57-9734-5024a184dde2
uIDPozugP+6QfqdMiSMwVvSSLHMAAAAAaH3evmpXbEuO3JjPz/SxLk78snnRQYxJqV2lNkOxrPsACQAA






Yaron Naveh (MVP) said...

Hi Syed - the xml is not seen well in the comment, please send me in a mail

Mohamed Kaboud said...

Hi Yaron,

Great work.

I am stuck with the following exception. I am not sure if it is the user name or something is not right.

Exception:
Message: "An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail."
FaultException (Inner Exception):
Message: "https://204.41.14.78:1441/EDTService/EDTService: cvc-simple-type 1: element username value '---@---.com' is not a valid instance of type {http://hcv.health.ontario.ca/}username"
Code:
IsPredefinedFault: true
IsReceiverFault: false
IsSenderFault: false
Name: "Rejected by Policy."
Namespace: "http://schemas.xmlsoap.org/soap/envelope/"

Thanks a lot.

Yaron Naveh (MVP) said...

Hi Mohamed

This error is not related to WCF. In one of the username fields you have provided a value which the server does not expect. Try comparing your outgoing message with a sample working message from documentation.

Maddy said...

hi mohamed,
For Testing, we do not pass MSA Header. send as empty (don't use MUSerId).

ex
MSAHeader msa = new MSAHeader();
that's all.

Maddy said...

hi mohamed,

send MSA Header as empty. do not bind the MUserId only that u got that error
ex
MSAHeader msa = new MSAHeader();


Paresh Dehadray Blog said...

Hi,

Your post is very useful. I am able to generate SOAP request which is asked by my client by below setting.

<customBinding>
<binding name="NewBinding0">
<textMessageEncoding messageVersion="Soap11" />
<security authenticationMode="MutualCertificate" messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10">
</security>
<httpTransport />
</binding>
</customBinding>

But I need one more tag "UsernameToken" which is missing. To get this tag instead of MutualCertificate I use UserNameForCertificate. Below is the system.serviceModel xml from web.config:

<system.serviceModel>
<diagnostics>
<messageLogging logEntireMessage="true" logMalformedMessages="true"
logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="true"
maxMessagesToLog="3000" maxSizeOfMessageToLog="500000" />
</diagnostics>
<bindings>
<customBinding>
<binding name="customConfig">
<textMessageEncoding messageVersion="Soap11" />
<security authenticationMode="UserNameForCertificate" messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10">
</security>
<httpTransport />
</binding>
</customBinding>
</bindings>
<services>
<service behaviorConfiguration="USAbleWCFService.AQUARatingServiceBehavior" name="USAbleWCFService.AQUARatingService">
<endpoint address="" binding="customBinding" bindingConfiguration="customConfig" bindingNamespace="https://USAbleWCFService.insurix.com" contract="USAbleWCFService.IAQUARatingService">
<identity>
<dns value="tempCertServer"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="USAbleWCFService.AQUARatingServiceBehavior">
<serviceMetadata httpGetEnabled="true" httpGetUrl=""/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="USAbleWCFService.CustomAuthentication,USAbleWCFService"/>
<serviceCertificate storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" findValue="tempCertServer" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>


But now I am unable to make the call from console application (where I added service reference). It is throwing exception "An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail.".

Please suggest me how I can provide UsernameToken and validate user by Username and Password.

I am able to successfully validate the user by Username and Password using wsHttpBinding but then in SOAP UI I don't have BinarySecurityToken. This tag I am getting with your way by using CustomBinding.

Please help me.

Thanks in advance!

Paresh

Yaron Naveh (MVP) said...

Hi Paresh

You can try add a username like this:

https://gist.github.com/yaronn/7894760

or even add it manually in a custom message encoder (depending if you need to sign it or not)

Elio Batista said...

Hi Yaron, I'm developing a client to consume a web service written in java using web security, thanks to your post series I get it working now in my development environment. Now I have a problem, when i run the application in the customer's network i get this error messaje from the service:

org.jboss.ws.core.CommonSOAPFaultException: An internal error occurred WS-Security. See log for details

My first reaction was Fiddler and found that the SOAP message structure remains the same as the generated in my development environment. According to the network administrator for the proxy / fiewall has no restriction at all.
With this facts I enabled tracing for the WCF client in my application but not further details appart for this erro rmessage.
I have no clue What could be causing this error? (Hopefully) Do you have address this before?

Elio Batista said...

Hi Yaron, can you please look at this question? Thanks very much.

Yaron Naveh (MVP) said...

Hi Elio

Please mail me the SOAP your client sends (use Fiddler to get it) and a sample working SOAP. Also sent the serve response from fiddler. In all cases please include the http headers. If there is any special error in the server logs send it too.

GrandpaJudah said...

Hi Yaron,
I'm doing what I thought was a simple conversion from .NET 2 to .NET 4 framework. I hadn't changed any code other than my configuration for the framework change. My basicHttpBindings still work, but my custom bindings do not. I get an error from the java web service: SECU3757: Unknown exception while performing decryption: java.security.InvalidKeyException: Illegal key size.

When I check with the WS owner he says the data is coming through in a different format. Here is the difference:
.NET 2 (successful request)


999999
CBI.Authorization.Devices



.NET 4 (failed request)









fUyx1wC9u1K4Bgb70U7PBmVoJ+CmZEnb4lwo6/1H6oCFsA2sMsw7Xd7MvYo9cAFlcXdcgOqpkkT28mlsb9aS/n2NdKBMqDNEMmEvOGM3C8BgIkjPUJIu0M+6zwUeIM8bcxoVdhaWvjWA66uPNpHoSZV+ecvecdpu2rdPPss0XxZhUCUL+uPxUT/VtcR+K/UmT4bKvCfLU2EzGwZicqTuCfNA9n397Q1Oxdf/h1/1Vud3W5VNhs4Vhw9Sh604Pq+Qst0dELmDruQm2B8agYmin9Z61sJgso5Q7OLH6z26dYuk9TLPXvB0KUeWHxRKd70qmby2bfIoqaE6XeR26p18zBiwpo2NQAXIDkjKdrNizVXD4Va9/jqf3aP9TZ0E1lXUitAxLOszCPra5tlc1e3uwTXw8dLq1A/4uyLU3bqU=




Any ideas?
Thanks, Judah

Yaron Naveh (MVP) said...

Hi

I can't see the XML in the comment - please send me in mail

Omer Kara said...

Hi Yaren, could you please also add Server side configuration and explain it. Because I want to test my client, but I am not sure If I am programming server side truly. If possible It would be better If you can share source code with us, your followers. Best Regards.

Yaron Naveh (MVP) said...

Hi Omer

There are many server settings from various frameworks. If you use WCF you would use the same server setting as the client settings.

In general you usually have an existing server setting and you try to consume it with WCF, which this post helps with.

A while ago I published sample client and server:

http://webservices20.blogspot.co.il/2010/01/axis2-wcf-interoperability.html

Yaron Naveh (MVP) said...

Hi Omer

There are many server settings from various frameworks. If you use WCF you would use the same server setting as the client settings.

In general you usually have an existing server setting and you try to consume it with WCF, which this post helps with.

A while ago I published sample client and server:

http://webservices20.blogspot.co.il/2010/01/axis2-wcf-interoperability.html

Özgür Özkan AKDEMİRCİ said...

Hi Yaron,
really thanks for the post...
The error I got is
{"The service certificate is not provided for target 'https://aa.bb.com/xtzt/bbbb/methodname'. Specify a service certificate in ClientCredentials."}
as in your confusion #4 I added a certificate in my trusted root certification authority store... (I would like to add the site's ssl server certificate but i cannot add it to my stores I think) This time, I got the DNS error (confusion #10). I fix it by adding identity dns tags, this time I got

"The HTTP request was forbidden with client authentication scheme 'Anonymous'"...

Do you have any new confusions =))

Thanks in advance...

Özgür

Yaron Naveh (MVP) said...

Hi Özgür

This means that in addition (or instead?) of messgae security you also have transport security. Maybe you need user/pass in the http level by setting an httpsTransport with authenticationSchema attribute. You need to get a sample working request (including http headers) and see how it looks.

Sergey Salasin said...

Hi Yaron
Thanks for your post.
I try to connect to a service(not our) using custombinding with mutualcertificate. Get "security processor was unable to find a security header.." I've changed enableUnsecuredResponse to true. The error has changed to "An error occurred when verifying security for the message". Tried to change ProtectionLevel - no difference. Please help. Thank you.

Yaron Naveh (MVP) said...

Hi Sergey

Do you have a sample working soap request (e.g. from the vendor, or soapUI)? You can mail it to me as well as your current binding)

Yaron

Cemal Tapan said...

Hi Norah,
In my sample is
BinarySecurityToken EncodingType="http://docs.oasisopen.
org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"
ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-tokenprofile-
1.0#X509PKIPathv1"

Bu Wcf creates:

ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"
EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"

The differece is
Java: X509PKIPathv1
.net: X509v3

Any other parts are correct in the soap. Is there a way to solve this problem?

thanks

Yaron Naveh (MVP) said...

for this specific difference I think it depends in the certificate you use. can you try to use another certificate (even temporarily)? what soapui creates? I also think it is safe to change this value manually (e.g. via an encoder)

Lee Koloszyc said...

Just checking into say thanks. I had been trying for two days to get SoapUI to be able to send successfully to my WCF Service even though I had a WCF Client that could.
I kept receiving "Signing without primary signature requires timestamp" from the soapUI calls and the only difference in XML was the Timestamp came first from the WCF client and last from soapUI. The securityHeaderLayout setting didn't do anything, but #9 on your post did as my messageSecurityVersion was WSSecurity11, switched it to WSSecurity10 and everything works great. Thanks again!

Yaron Naveh (MVP) said...

Very happy to hear that Lee!

Uas Ku Sukses said...

Hi Yaroh,

I've a problem when invoke the webservice

Here is the error "Unable to identify WSDL operation from message from {0}." soap:Server.80031

Can you help me about this error ?

Yaron Naveh (MVP) said...

at what stage do you get this error? add service reference or run time?

Uas Ku Sukses said...

Hi Yahon,

Currently i got the problem when request to the server.
Here is my error

Exception during processing: javax.xml.soap.SOAPException: Unable to handle mustUnderstand header: o:Security (see Fault Detail for stacktrace)

im using .net to call java services

i guess it should be remove the

how i can remove it?

Thanks alot

stanley haun said...

Hi Yaron,

C# WCF Client to Java AXIS Service in Azure. Got the following exception when loading the certification file using the following code:
client.ClientCredentials.ServiceCertificate.DefaultCertificate = new X509Certificate2(certServerPath);
System.Security.Cryptography.CryptographicException: Cannot find the original signer. at System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr) at System.Security.Cryptography.X509Certificates.X509Utils._LoadCertFromBlob(Byte[] rawData, IntPtr password, UInt32 dwFlags, Boolean persistKeySet, SafeCertContextHandle& pCertCtx) at System.Security.Cryptography.X509Certificates.X509Certificate.LoadCertificateFromBlob(Byte[] rawData, Object password, X509KeyStorageFlags keyStorageFlags) at System.Security.Cryptography.X509Certificates.X509Certificate..ctor(Byte[] rawData, String password, X509KeyStorageFlags keyStorageFlags) at System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(Byte[] rawData, String password, X509KeyStorageFlags keyStorageFlags) at

Any clue how to fix this problem?
Thanks.

// Stanley Haun

Yaron Naveh (MVP) said...

Hi Stanley

Check this:
http://stackoverflow.com/questions/19190404/loading-x509certificate-results-in-exception-cryptographicexception-cannot-find

Also I suggest to try it on another machine (not yours and not Azure) to see the behavior.

Shobhit Agarwal said...

Hi yaron,
I am getting below error when try to consume a web service in asp.net:
System.ServiceModel.FaultException: Signature verification failed
message signing is required here using X509 certificate. Can you guide me here.8

madanforall said...

Hi Yaron,

i am getting bellow error while i consuming wcf services using x509 certificate..i follow your post as usual but still getting error

signature or decryption was invalid

any help ?

thanks
madhan

Yaron Naveh (MVP) said...

if you built a custom encoder make sure it does not change any signed parts in the xml (also not whitespace).

madanforall said...

hi i am not use any custom encoder..followed your post only and how can make some encrypt body elements using wcf for ex












Encrypted message body






is it possible using .net ?

Pierrick Venon said...

Hi Yaron,
I'm try to consume a webservice that appears to be written in java and that requiert some element of WS-Security: signature, timestamp and username.
I have created a x509 certificate to sign the request and I was provided with a username and a password to use with the request
I manage to make it work using SoapUI here is a link to the request capture using fiddler: http://pastebin.com/LbMp6nyG

The final goal is to consume this service in a .net web application, i've created a sample and try different configuration
I have an error : "An error was discovered processing the header"
here is the request send by the web application: http://pastebin.com/hLG0k5jN
here is the web.config configuration that I use: http://pastebin.com/9BECTEnT

The request is somehow similar to the soapui one but not the same, can you point me in the right direction?
it seems that the .net call does not send the username and password even if I set them in the code like this:
GererContratTelesurveillanceClient tls = new GererContratTelesurveillanceClient();
tls.ClientCredentials.UserName.UserName = "tlsprows";
tls.ClientCredentials.UserName.Password = "123";

Yaron Naveh (MVP) said...

Hi Pierrick, in order to add a username token to a mutualcertificate binding, either use something like this https://gist.github.com/yaronn/7894760 (might need to fine tune) or add the username tags in a message inspector (they will not be signed but you do not need it anyway).

Pierrick Venon said...

Hi, I've tried to manualy set up the binding using your link https://gist.github.com/yaronn/7894760 but I have a problem with the line:
new ServiceReference1.SimpleServiceSoapClient(b, new EndpointAddress(new Uri("https://www.bankhapoalim.co.il/"), new DnsEndpointIdentity("WSE2QuickStartServer"), new AddressHeaderCollection()));

What is this class? my service class generated after adding the service reference in the web application does not have a constructor with that many parameters.

a other question is why setting up the username and password using ClientCredentials is not working with mutualcertificate? (no node in the soap header is created)

Yaron Naveh (MVP) said...

user/pass + client certificate will not work declaratively with xml binding. you can create them via code like I sent or with mutualcertificate I beleive. This is a default ctor for a service proxy, maybe it's in partial class in anotehr file or in a base class, which ctor you have?

Innovaminds said...

Hey Yaron,
How I can change the order of header elements? I need security element first and then Action element, but my custom binding generates Action element first and then security element.


Regards,
Amit

Yaron Naveh (MVP) said...

there should be a protectionOrder setting on the security channel of a custom binding but it that does not help the only way is to implement a custom encoder and change the order of the generated message.

Innovaminds said...

Can you please check, your email. I have requested you through email along with the code I am using for the same. In the meantime I will try this too on my end.


Regards,
Amit

Alexander Iskrenov said...

This is the finest read out there on the topic. You saved me hours of MSDNing. God bless you man. Cheers!

Anisa Sama said...

I am facing same issue . Binary security token is not being sign in my message. I have tried almost all options.Please guide.BST id should be refer in signedinfo elemnt. This is required by server.

my code is

AsymmetricSecurityBindingElement secBE = (AsymmetricSecurityBindingElement) (SecurityBindingElement.CreateMutualCertificateDuplexBindingElement());
secBE.MessageSecurityVersion = MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11;
secBE.InitiatorTokenParameters = new System.ServiceModel.Security.Tokens.X509SecurityTokenParameters { X509ReferenceStyle= X509KeyIdentifierClauseType.Thumbprint, InclusionMode = SecurityTokenInclusionMode.AlwaysToRecipient, ReferenceStyle = SecurityTokenReferenceStyle.Internal };
secBE.RecipientTokenParameters = new System.ServiceModel.Security.Tokens.X509SecurityTokenParameters { X509ReferenceStyle = X509KeyIdentifierClauseType.Thumbprint, InclusionMode = SecurityTokenInclusionMode.Never, ReferenceStyle = SecurityTokenReferenceStyle.Internal };
// secBE.EndpointSupportingTokenParameters.Endorsing.Add(secBE.InitiatorTokenParameters);
// secBE.KeyEntropyMode = SecurityKeyEntropyMode.ClientEntropy;
secBE.AllowInsecureTransport = true;
secBE.ProtectTokens = true;
secBE.SetKeyDerivation(false);
secBE.DefaultAlgorithmSuite = SecurityAlgorithmSuite.Basic256Sha256;
secBE.RequireSignatureConfirmation = true;
secBE.AllowSerializedSigningTokenOnReply = true;
secBE.MessageProtectionOrder = MessageProtectionOrder.SignBeforeEncrypt;
secBE.SecurityHeaderLayout = SecurityHeaderLayout.Lax;
secBE.EnableUnsecuredResponse = true;
secBE.IncludeTimestamp = true;
HttpsTransportBindingElement elem = new HttpsTransportBindingElement { RequireClientCertificate = true };
CustomBinding binding = new CustomBinding(secBE, new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8), elem);



Dds.Endpoint.Binding = binding;
Dds.Endpoint.Contract.ProtectionLevel = System.Net.Security.ProtectionLevel.Sign;


Anthony Yeoman said...

Thank you for this. The info here really helped me on my first WCF project.