Thursday, April 30, 2009

Introducing WCF ClearUsernameBinding

@YaronNaveh




Update
: ClearUsernameBinding is now hosted on GitHub. This post contains the updated usage instructions.


Using cleartext username/password is usually not recommended. However it is sometimes required (like with F5's BIG-IP). WCF does not natively allow us to use such scenario. For this reason I have written ClearUsernameBinding - a WCF binding that enables to send cleartext username/password over HTTP.

Full source code is available in google code github.

So without any further preparations let's see how to use ClearUsernameBinding.

Step 1: Download latest release
Download it here or go to google code github.
Then extract the zip to some folder, let's say C:\program files\ (the ClearUsernameBinding subfolder will be created when extracting the zip).

Step 2 (optional) - Run the sample project
It can be useful to run the sample application.

Run the server:

C:\program files\ClearUsernameBinding\TestService\bin\Release\
TestService.exe




And now the client:


C:\program files\ClearUsernameBinding\TestClient\bin\Release\
TestClient.exe




And if everything went smoothly you have just seen ClearUsernameBinding in first action!

Step 3 (optional) - Investigate the sample project source code
The best way to learn a new (and very simple in this case) technology is by looking at existing projects. Just open with VS 2008 the solution file:


C:\program files\ClearUsernameBinding\ClearUsernameBinding.sln


And look at the source of the projects TestClient and TestService. These two projects are just normal WCF projects configured to use ClearUsernameBinding. In other words, making a WCF client/service use ClearUsernameBinding is just a matter of changing web.config and does not require coding. We will see in the next steps how to do it from scratch.

I'll probably have a separate post on the binding implementation itself. It is pretty straight forward and the handling of security is as I learned from Nicholas Allen's blog.

Step 4 - Creating your own service
For this step just create any normal WCF web site or a self hosted service.

Step 5 - Configure the service to use ClearUsernameBinding
Add your project a dll reference to


C:\Program Files\ClearUsernameBinding\ClearUserPassBinding\bin\
Release\ClearUsernameBinding.dll


Then open web.config and register the ClearUsernameBinding under the system.ServiceModel section:



<extensions>
  <bindingExtensions>
   <add name="clearUsernameBinding" type="WebServices20.BindingExtenions
.ClearUsernameCollectionElement, ClearUsernameBinding" />
  </bindingExtensions>
</extensions>

<bindings>
  <clearUsernameBinding>
   <binding name="myClearUsernameBinding"
messageVersion="Soap12">
   </binding>
  </clearUsernameBinding>
</bindings>


Finally configure your endpoint to use ClearUsernameBinging and its configuration:


<endpoint binding="clearUsernameBinding" bindingConfiguration="myClearUsernameBinding"
contract="WebServices20.SampleService.IEchoService" />


An example of the complete web.config is inside the full project binary&source in


C:\Program Files\ClearUsernameBinding\TestService\bin\Release\
TestService.exe.config


Step 6 (optional) - Configure the message version
If you need to use a specific message version configure it in the "messageVersion" attribute in the above configuration. Valid values are: Soap11WSAddressing10, Soap12WSAddressing10, Soap11WSAddressingAugust2004, Soap12WSAddressingAugust2004, Soap11, Soap12, None, Default.

Example:


<binding name="myClearUsernameBinding" messageVersion="Soap12">
</binding>


Step 7 - Configure the username authentication
This one needs to be done in any username/password authenticated service and not just one that uses ClearUsernameBinding. By default your server will authenticate the users against your active directory domain. If you want to do your own custom authentication you need to create a new class library project with a class that implements System.IdentityModel.Selectors.UserNamePasswordValidator

The class can look like this:



public class MyUserNameValidator : UserNamePasswordValidator
{
  public override void Validate(string userName, string password)
  {
   if (userName != "yaron")
    throw new SecurityTokenException("Unknown Username or Password");
  }
}


Don't forget to add dll reference to System.IdentityModel and System.IdentityModel.Selectors or the project will not compile. Then add this project as a project reference to your service project/website and configure the latter to use this custom authenticator:


<behaviors>
  <serviceBehaviors>
   <behavior name="SampleServiceBehaviour">
...
    <serviceCredentials>
    <userNameAuthentication     userNamePasswordValidationMode="Custom"
    customUserNamePasswordValidatorType=
"WebServices20.Validators.MyUserNameValidator, MyUserNameValidator" />
    </serviceCredentials>
   </behavior>
  </serviceBehaviors>
</behaviors>
...
<service behaviorConfiguration="SampleServiceBehaviour" name="WebServices20.SampleService.EchoService">
...


Again the full sample is available for download.


Step 8 - Run the service
Yes, the service is now ready to be activated, so run it when you are ready (run it directly from VS, just press F5).


Step 9 -Build a client
A service is worth nothing if there are no clients to consume it.
Create a new console application.
Right click the "References" node in the solution explorer and choose "Add service reference". Specify the WSDL of the server. If you are running the server from the given sample then the wsdl is in http://localhost:8087/SampleService/?WSDL. If you used your own server just run it and get the wsdl.

Now add some client code that uses the proxy to call the service. Don't forget to specify your username/password. For example:



ServiceReference1.EchoServiceClient client = new TestClient.ServiceReference1.EchoServiceClient();
client.ClientCredentials.UserName.UserName = "yaron";
client.ClientCredentials.UserName.Password = "1234";
client.EchoString("hello");



Step 10 - Configure the client
Configuring the client is as simple as configuring the service.
Here is the full client app.config:



<system.serviceModel>
  <client>
   <endpoint address="http://localhost.:8087/SampleService/" binding="clearUsernameBinding"
   bindingConfiguration="myClearUsernameBinding"   contract="ServiceReference1.IEchoService"
   name="ClearUsernameBinding_IEchoService" />
  </client>

  <extensions>
   <bindingExtensions>
    <add name="clearUsernameBinding"    type="WebServices20.BindingExtenions
.ClearUsernameCollectionElement   , ClearUsernameBinding" />
   </bindingExtensions>
  </extensions>

  <bindings>
   <clearUsernameBinding>
    <binding name="myClearUsernameBinding"
messageVersion="Soap12">

    </binding>
   </clearUsernameBinding>
  </bindings>

</system.serviceModel>



Step 11 - Done, Done, Done!
That's all. You can now run your client and see how WCF can be used to access a service with a cleartext username/password. Use a tool like fiddler to verify that indeed a clear username is sent (I've shorten some low-level stuff from bellow message):


<Envelope>
  <Header>
   <Security>
...
    <UsernameToken>
     <Username>yaron</Username>
     <Password>1234</Password>
    </UsernameToken>
   </Security>
  </Header>
  <Body>
   <EchoString xmlns="http://tempuri.org/">
    <s>hello</s>
   </EchoString>
  </Body>
</Envelope>


Conclusion
Sending username/password on the clear is not available out of the box with WCF (for reasons mentioned above). If such a scenario is required then ClearUsernameBinding needs to be used.

@YaronNaveh

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

243 comments:

«Oldest   ‹Older   1 – 200 of 243   Newer›   Newest»
machey said...

I tried using this to connect to the CXF-based service. It requires a username/password sent in clear text, but the connection fails, with the error below. Have you seen/solved an issue like this before?

The content type text/xml;charset=UTF-8 of the response message does not match t
he content type of the binding (application/soap+xml; charset=utf-8). If using a
custom encoder, be sure that the IsContentTypeSupported method is implemented properly. The first 305 bytes of the response were:
faultstring

The security token could not be authenticated or authorized.

machey said...

correction.... a CXF-based service....not the CXF-based service.

Yaron Naveh said...

Hi Machey

Note that the error is with WCF handling the response. If you will use a tool like Fiddler or WCF logging you will see the actual response which might be the expected one or some other error.

It seems the service uses Soap11 but your client uses Soap12 (probably because this is the ClearUsernameBinding default).

Try set it like this:

<binding name="myClearUsernameBinding" messageVersion="Soap11">

</binding>

Let me know how it goes.

Sachin said...

How does this work in IIS hosted environment with SSL certificate. Also in order to provide interoperability how will the clients using non woindows environment will be able to provide the user credentioals?

Yaron Naveh said...

Hi Sachin

When SSL is used there is no need for clearUsernameBinding - you can use the out of the box WCF configurations.

As for interoperability, clearUsernameBinding adheres to the WSS username profile.

Pierre-Alain Vigeant said...

What is required to be changed in order to use TCP transport (net.tcp) with your ClearUsernameBinding?

I changed the Scheme to "net.tcp" and the HttpTransportBindingElement into TcpTransportBindingElement.

But I keep getting an error of NullReferenceException.

I thought that it was my code, but the trace is nowhere close to what I coded.

I traced the error:

System.NullReferenceException: Object reference not set to an instance of an object.
at System.ServiceModel.Channels.TransportOutputChannel..ctor(ChannelManagerBase channelManager, EndpointAddress to, Uri via, Boolean manualAddressing, MessageVersion messageVersion)
[middle of trace skipped]
at System.ServiceModel.Channels.ServerSessionPreambleConnectionReader.ContinueReading()

Do you have any idea?

Yaron Naveh said...

Pierre

Why do you need this capability with netTcp? Generally netTcp implies a WCF2WCF scenario in which case there should not be any interoperability problems.

Looking at the reflector it seems that the function that the exception is thrown from uses the MessageVersion property of the binding. Also it seems that MessageVersion.None - which is the default value in ClearUsernameBinding - has its data member Addressing.anonymousUri set to null and this might cause the error.
You can use the configuration file to set a different addressing version to ClearUsernameBinding or change the default in ClearUsernameBinding.cs (as you have already done code changes).

Currently the configuration file has:

messageVersion="Soap12"

Instead you can use

messageVersion="soap11Addressing10"

Let me know how it went.

Yaron

Pierre-Alain Vigeant said...

Thank you. It does work. Why it is always something easy? hehe

My application is indeed a WCF-WCF client-server.

I wanted to use Username authentication, even if it was in clear text for development purpose. We need a custom username validator.

As soon as the company can supply me with a valid certificate, I will switch the binding to use a certificate.

Another reason why I choosed Tcp over Http was for developing under Vista. The service has to be run in administrative mode or the http service cannot register. It raise an error about not having the right to open a port on "http://+:port/Service1".

Anonymous said...

Thank you for the article.

This is similar to what I'm trying to attempt to solve but not quite:

I want to use shared secret. That is, symetric encryption. I know the secret passcode (512 bit hash) on both sides of the communication, and I'll send encrypted and attempt decrypt on the other side. If the shared secret is wrong, it won't be able to decrypt and it will fail. Thus I have authentication at the same time.

The shared secret is stored in a database with an encrypted value that has to be decrypted by the application which has been obviscated which makes it pretty darn secure, although obviously it isn't as secure as the certificate store, however, any user app running wil have access to certificate store anyhow, so it's about the same.

How does one go about doing symetric encryption without authentication (or the authentication happening within the symetric encrypted message)?

Thanks!

Yaron Naveh said...

Hi Anonymous

I think you have a different scenario. You should look in WCF security extensibility and implement a custom token or token provider.
The delicate point with what you mentioned is that there is one secret to both parties, i.e. no PKI. In this case if one party chooses to renounce his message he can claim the other one faked it.
Also you have to use digital signature to prevent replay attacks.

Mansoor said...

Hello,
Thanks for the binding however i am running into another issue. I am trying to hook up to a JAVA base service that is expecting WS-Security 1.1 header but your binding is producing WS-Security 1.0 headers. Is there anyway to correct that?
Thanks

Yaron Naveh said...

Mansoor

When just a username is used there should be no difference between WSS1.0 and WSS1.1. Do you have a sample valid request to this service?

MAnsoor said...

The problem is that in WSS1.1 username and password are in different namespace as compared to WSS1.0. Blogger is not letting me paste the security header here so i have uploaded the request on this webserver. Please take a look

http://www.mediafire.com/?sharekey=386eb3cdfbc3a6f641446e35a78dc463e04e75f6e8ebb871

Yaron Naveh said...

The differences are the missing Type attribute in WSS1.0 and the missing nonce/timestamp.

Just for the purpose of testing try to use this function instead the existing one in ClearUsernameBinding.cs:

public override BindingElementCollection CreateBindingElements()
{
var res = new BindingElementCollection();
res.Add(new TextMessageEncodingBindingElement() { MessageVersion = this.messageVersion});
TransportSecurityBindingElement security = SecurityBindingElement.CreateUserNameOverTransportBindingElement();
security.MessageSecurityVersion = MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10;
res.Add(security);
res.Add(new AutoSecuredHttpTransportElement());
return res;
}


This is supposed to fix the "Type" issue. As for the nonce/timestamp - I'm not sure your service realy requires them - but if so there is no OOTB way to add them and mabe a custom token serializer needs to be written.

Mansoor said...

That actually solved the problem. Thank you for your help

Yaron Naveh said...

Glad to hear.

Actually the correct solution is to put this as a configuration option similar to what I did with the soap version. I'll do it when I have time.

Mansoor said...

Sorry to bother you again, but i just wanted to ask you if you know how i can add WS-Addressing headers to my soap request as well. Java Service also requires WS-Addressing headers

Thanks

Yaron Naveh said...

the configuration contains a place for the soap version (default is Soap11) you can set it to Soap11WSAddressingAugust2004 for example - these are the same values as usually in WCF

Mansoor said...

Hey Yaron,

Just wanted to tell you that everything is working fine now due to your help.

I am pretty well versed in doing web services on Java side but WCF is a totally new animal. Your blog is a valuable resource when it comes to WCF.

I was wondering if you would blog about sending and receiving SAML assertions in SOAP Headers in near future? I know how to do this in Java but i want to do the same with WCF

Thanks

Yaron Naveh said...

Mansoor

I don't know if I'll get to it soon but there should be a lot of stuff on "wcf federation". There is even a sample for this in the WCF SDK.

BTW which framework do you use on the Java side?

Mansoor said...

Yaron,

I am using Xfire/CXF on Java side.

Another quick question though, for Ws-Addressing i am setting Soap11WSAddressingAugust2004 as the messaging version. DO you know what I need to set for WS-Addressing 2005 version? I googled but could not find property for 2005 version of WS-Addressing

Thanks

Yaron Naveh said...

The 2005 version is Soap11WSAddressing10

Шерлок said...

Thanks for your contribution, it's just what I need for my situation.

I think there is a minor error.
In order for this to work you're specifying custom bindingExtension
[add name="clearUsernameBinding" type="WebServices20.BindingExtenions.ClearUsernameCollectionElement, ClearUsernameBinding" ]
However class ClearUsernameCollectionElement is defined as internal, hence not accessible, which prevents it from being loaded.

But thanks for making source code available, that's a minor issue

Yaron Naveh said...

Шерлок

What you said makes sense.

However the sample project also has sample working client/server which are working even though this is internal class. Did you do anything different then in these samples?

Anonymous said...

Hello Yaron.

I tried to follow this using a VS2008 VB program and i am getting nowhere. I got the following error before i tried your changes and i'm still getting it.

Unhandled Exception: System.ServiceModel.CommunicationException: Could not connect to https://www.xatanet.net/XataNetWebService/TripExportService.asmx.
TCP error code 10013: An attempt was made to access a socket in a way forbidden by its access permissions 209.46.25.197:443.
---> System.Net.WebException: Unable to connect to the remote server ---> System.Net.Sockets.SocketException:
An attempt was made to access a socket in a way forbidden by its access permissions 209.46.25.197:443

Clould you help me resolve this for a VB program?

Thanks,
Tony

Yaron Naveh said...

Tony

Looks like a firewall or something else is blocking you.

Can you access this address from IE?
Can you try from another PC?

Cave said...

I have a method with output param byte[]. Client receive this error:

The maximum message size quota for incoming messages (65536) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element.

How can i incrase the quota with ClearUsernamebinding?

tnx

Cave said...

I created a constructor for AutoSecuredHttpTransportElement and i set:
MaxReceivedMessageSize = int.MaxValue;
MaxBufferSize = int.MaxValue;
MaxBufferPoolSize = long.MaxValue;

now there is another problem:

Error in deserializing body of reply message for operation 'Dm_Profile_GetDocument'. The maximum array length quota (16384) has been exceeded while reading XML data. This quota may be increased by changing the MaxArrayLength property on the XmlDictionaryReaderQuotas object used when creating the XML reader. Line 1, position 100898.

Have you got a solution?

Tnx

Yaron Naveh said...

Cave

When adding the textMessageEncoding element you can configure its ReaderQuotas.MaxArrayLength.

Yaron

jabits said...

Thanks for the very useful article and code! I have a further question.

You responded to an earlier question about using over ssl:

"When SSL is used there is no need for clearUsernameBinding - you can use the out of the box WCF configurations."

Ok, but suppose we need to for some reason run it in a different location that is using https; it looks like in the ClearUsernameBinding class, the Scheme property returns "http". Does this mean it will not work over ssl? Is there a way to use it with both protocals?

Thanks, jabits

Yaron Naveh said...

jabits

Currently clearUsernameBinding is locked to http. However it can be extended to support https by:

1. Adding a configuration to determine which schem should be used, similarly to the way MessageVersion is configured now (see SetMessageVersion() in ClearUsernameBinding.cs and more)

2. The "Scheme" property should return http or https depending on the configuration

3. CreateBindingElements should add HttpsTransportElement instead of AutoSecuredHttpTransportElement

If you do not want to add this now then you should switch to basicHttpBinding in your code whenever you need ssl.

Larkin said...

Great post, Yaron.

I just had a question regarding metadata publishing. Is the security policy not specified in the generated WSDL? Of course it is not required, as you can simply provide the username/password token according to the standard from most clients, but I have a requirement that all security policy information be present in the WSDL file. Any ideas or suggestions on this?

Thanks,
Larkin

AndyKing said...

Dear Yaronn,

I've implemented your ClearUsernameBinding.dll into my system which has worked well so thanks for that.

However, when I trying and update the service references i get the following error:

Error 32 Failed to update Service Reference 'SanzarToUmbStaffServiceReference.Reference'.
Error:The configuration for the service reference could not be updated due to the following issue: An error occurred creating the configuration section handler for system.serviceModel/bindings: Could not load file or assembly 'ClearUsernameBinding' or one of its dependencies. The system cannot find the file specified. (C:\temp\Sanzar Partnership\Checkout\Web\Web.config line 242)(0x80131902)

Also, when i tried and build the deployment project I get a similar error:
Error 6 An error occurred creating the configuration section handler for system.serviceModel/bindings: Could not load file or assembly 'ClearUsernameBinding' or one of its dependencies. The system cannot find the file specified. (C:\temp\Sanzar Partnership\Checkout\Web_deploy\ReleaseSasoonUS\web.config line 242) 1 1 Web_deploy

My solution consists of a website and a wcf service application. Both have your dll in the bin with references. I have other dll's in my bin folder like aspose cells and ABCPDF and have no problems with these.

I would greatly appreciate any help on this as if I cant resolve it then I'll have to remove ClearUsernamebinding and start from scratch.

Thanks,
Andy Weeks

DaveBlack said...

Hi Yaron,

Very helpful blog - thank you!

I have 2 questions.

1. I'm trying to configure a WCF Service that will be accessed by a WSE 3.0 Client. I see lots of examples of how to *consume* a WSE service from a WCF Client but not the reverse. How do I do this using configuration file?

2. The same WCF Service mentioned above will communicate with its Clients over SSL. I don't see a clear example of how to do this. I'd like to use a configuration file.

Any assistance you can provide is greatly appreciated :)

Yaron Naveh said...

Larkin

Unfortunately it seems one would need the AutoSecuredHttpTransportElement class to implement IPolicyExportExtension and manually provide the policy, as the framework policy dealing functions are internal.

Yaron Naveh said...

Andy

I'm not sure why this happens, are you signing your assemblies in any way? Can you create a separate simple web site just for testing and try clearUsernameBinding on it? Is it reproduced on another machine? Can you share the code?

Yaron Naveh said...

Dave

Which security do you plan to use on the service? Just ssl? Anyway you should generally stick to basicHttpBinding, and in the case of ssl configure it with security mode of transport. You can see the equivalent examples of WCF clients and take the configuration from there.

AndyKing said...

Hi yaron

I'm still getting the error but have worked around it for the time being by not performing the servicemodel config replacements in the deploy project.

However, i'm getting another error now. "The maximum string content length quota (8192) has been exceeded while reading XML data. This quota may be increased by changing the MaxStringContentLength property on the XmlDictionaryReaderQuotas object used when ..." etc.

How do i specify the MaxStringContentLength in the config file or progrmatically?

Thanks

Yaron Naveh said...

Andy

The cleanest way is to add a configuration for this as I did for the message version. search for "MessageVersion" in the code and see how it is implemented.

If you want a quick way to test it before going the full path then in ClearUsernameBinding.cs in the CreateBindingElements() method see the second line. It creates a TextMessageEncodingBindingElement and initializes it with the message version, use the same place to also intizlize the ReaderQuotas element with the correct limit on the property the error gives you. Note you need to add the project a reference to System.Runtime.Serialization.

AndyKing said...

Are you saying i'm going to have to progrmatically change your project to add this new property so i can declare it here:

&lt binding name="myClearUsernameBinding" messageVersion="Soap12" %gt
?

Does your project not inherently do this?

Yaron Naveh said...

Yes Andy.

The WCF model requires each attribute on these elements to be progrmatically defined. I have done so only for the basic stuff, there are many possible attributes there.

The alternative as I mentioned is to hard code it.

Alex said...

Hi Yaron,

I am trying to consume a service, which requires me to pass a usernam/password in clear text. That service is written in Java and is on Apache web server.

I am trying to follow your example for configuring the client, since server is provided to me, but it does not seem to work.

When modifying app.config I get an error on "<"clearUsernameBinding">", which states:

"The element "bindings" has invalid element 'clearUsernameBinding'. List of possible elemnts expcted: 'basicHttpBinding'..."

THanks for your help.

Alex

Yaron Naveh said...

Alex

Make sure your app.config is similar to the sample one - in particular make sure you have the "extensions" section.

Alex said...

I did, but I still get that error. In fact, even in your project VS2008 shows the same error.

Yaron Naveh said...

Alex

Do you mean that the sample as is does not run? I know it has run on many environments already. Can you check on another machine?

What about the WCF SDK custom binding sample (%WCF SDK Samples%\Extensibility\Binding\NetHttpBinding\) - does it run on your machine?

Weverton Gomes de Morais said...

I'm in need to do the same, but with a Silverlight client e it doesn't have some interfaces, like ISecurityCapabilites. Is there another way??

Thanks

Yaron Naveh said...

Weverton

In this case I think you cannot use clearUsernameBinding. Instead you need to manually add the username header to the soap using a MessageInspector.

Larkin said...

Yaron,

Thanks for your reply. I tried researching how to implement IPolicyExportExtension to export the policy metadata for the UsernameToken security, but I admit I am not anywhere near as seasoned an expert at WCF as you.

Would you mind pointing me in the right direction as to how to do this? I know that AutoSecuredHttpBindingElement needs to implement the IPolicyExportExtension.ExportPolicy method, but I am unsure of what I need to do to export the appropriate policy metadata. I tried browsing through the SecurityBindingElement source but I am a bit lost. Any help you could provide would be greatly appreciate.

Thanks,
Larkin

Yaron Naveh said...

Larkin

Automatically generating the "right" policy for your service seems hard as most of WCF relevant code is private.

My suggestion is to "hard code" inside the wsdl the correct policy for your use case. It might only include the clearUsernameBinding relevant section if this is the only standard you apply.

One way is to locally save the wsdl and change it - not very maintainable. You could automate this by implementing IPolicyExportExtension.

Your implementaiton for ExportPolicy should look something like this:

var doc = new XmlDocument(); doc.LoadXml(@"<myPolicy&gy;inner data</myPolicy>"); context.GetBindingAssertions().Add(doc.DocumentElement);

Where the LoadXml takes your hard coded policy. I'm actually not sure how this policy should exactly look like - you can find it out by setting up web service with the same requirements in an environment that natively support this scenario (e.g WSIT, Axis2). You can also see the policy for the default WCF username over transport scenario and remove from it the ssl related section.

Sorry I don't have the full details for this - I hope to take another look when I have time.

Simon Zhou said...

Hi Yaron,

I'm consuming a JAVA web service using WCF. The service url can be accessed through https. But I fail all the time. I've followed your suggestion to create a "clearUsernameBinding" but failed. Could you give me more advice? Thanks very much!

Yaron Naveh said...

Simon

If the server uses https then you do not need clearUsernameBinding. Use the OOTB WCF bindings.

If there is an error, ask from the service provider to supply you with a sample working soap message and compare it to the one you send.

Simon Zhou said...

Thank you for the reply. But I always get the same exception:
The provided URI scheme 'http' is invalid; expected 'https'.
Parameter name: via

Sounds like a client configuration issue. Any idea? Thanks again~~

Yaron Naveh said...

Simon

This means that your binding is configured to use ssl but the address you try to send to is not https.

Larkin said...

Yaron,

In your previous reply to my comment, you mention removing the SSL-related info from the policy metadata. I assume that this would include the entire TransportBinding element?

For example, the only element that I actually need is this:

<sp:SignedSupportingTokens xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:UsernameToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
>sp:WssUsernameToken10/>
</wsp:Policy>
</sp:UsernameToken>
</wsp:Policy>
</sp:SignedSupportingTokens>

Yaron Naveh said...

Larkin

I think so, but to be on the safe side I would set up a service with a similar configuration in Axis2/WSIT and verify the exact format.

Larkin said...

Yaron,

I didn't want to go through setting up a complete AXIS2 environment, but I did find a sample WSDL implementing the UsernameToken policy. I was partially correct, but I needed to change the SignedSupportingTokens element to the SupportingTokens element. This makes sense, of course, since we are not signing, encrypting, or endorsing the token in any way.

After spending a great deal of time tracing through the System.ServiceModel source code I have a better idea of what needs to be done to properly implement this, but as you said, it is a rather difficult and convoluted process. I only wish MS hadn't made so many of the supporting classes private and internal. For the moment I have essentially hard-coded the policy assertions, although it is a bit more elegant than it sounds.

Thanks for your help,

Larkin

Evgeni said...
This comment has been removed by the author.
Evgeni said...

Hi Yaron,

Thank you for sharing this, it was very helpful. In my scenario I using TCP protocol, so I adapted your solution properly (as described here in comments), and it works fine. However, when I defining a metadata exchange endpoint and trying to consume it on the client side (for example, using 'update service reference' option), in the client configuration generated info for the netTcpBinding, instead of ClearUserName binding... If I trying to call service anyway, I got an exception: "An error occurred when verifying security for the message". I really don't like to copy and paste my configuration, so is there any "right" solution to get both data contracts and the right configuration from metadata? (I think this question is related somewhat to the Larkin's one).

Thanks in advance,
Evgeni

P.S.
You asked someone in comments, why he using this with TCP protocol. I working in defense sector, and using user name / password to get user roles (instead of username validator, I using ASP role management). In some scenarios when I need security, I will use standard tcp / http bindings. However, most of the time I working in secured military networks, and there is no need to waste server's CPU and precious time for the data encryption. According to my checks, sending data not encrypted using yours binding is at least 4 times faster that sending encrypted one. This way, I can change binding according to the scenario and performance requirements, without changing any code!

Yaron Naveh said...

Evgeni

Thanks for sharing that information.

You question seems to be related to Larkin's one. You should use the same IPolicyExportExtension as I explained to him in order to add the metadata to the policy. The equivalent IPolicyImportExtension should be used at the client side.

Here is a good example for both sides:

http://msdn.microsoft.com/en-us/library/system.servicemodel.description.policyconversioncontext.aspx

Yaron Naveh said...

For everyone who asked: the ClearUsernamebinding sample uses self hosting but is easily portable to iis and works there smoothly too.

Karthik said...

I get a MessageSecurityException back from the server. I get a soap response back( sniffed via Wireshark) but exception is thrown.

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.

Yaron Naveh said...

Karthik

Does this error come from the server (e.g. does it appear in the wireshark response) or does wireshark shows a valid response and the client throws an exception.

Do you use ClearUsernameBinding on the client or server side?

Either way look at the request and response that are send with the sample application supplied and compare them to yours.

Karthik said...

Yaron,
Thanks for the response. I'm using the clearusernameBinding on the client side (WCF) consuming a java Axis web service. The bindings are exact same as the example you provided .

Wireshark gives me a normal xml response when sniffed from Axis and has any empty soap header. whereas WCF looks at that and throws me a Message Security exception.

I have attached a copy of Request and Response capured from wireshark I can't figure out what WCF is expecting from the Server .

http://tinypic.com/r/33kssoh/4

Yaron Naveh said...

Karthik

Configure WCF trace on the client side to get a detailed error.

My guess is that the client expedcts to get a timestamp - since it also sends one.
In the clearUsernameBinding code search for the place where the synnetric security element is created and set includeTimesatmp to false.

Yaron Naveh said...

BTW the correct way is of course to expose this as a configuration in the config file as done with soap version for example...

Karthik said...

It works now, by making timestamp=false in the clearUsernameBinding.cs.

Yes you were right, the WCF was expecting a timestamp back and Axis was not sending that back.

Thanks a lot Yaron !!!

Ajay Singh said...

Can this be used for WCF Service Application hosted in IIS 7.0 in Partial Trust Mode in conjunction with ASP.NET Membership Provider for Authentication?

Yaron Naveh said...

Ajay

I don't see any reason why not, though I haven't tried it myself. The validation mode (asp.net membership) is really orthogonal to the binding so it should work.

Pedro said...

When a use ClearUsernameBinding i get the exception "An error occurred when verifying security for the message". If i use another bind (with authentication) it's works. Do you have any idea?

Anonymous said...

Yaron,
I'm currently using ClearUsernameBinding in several services which use PasswordText for the Type. Everything works nicely. However there is a new service which requires PasswordDigest, and we can not use SSL or certificates at this point. Is this something I can do with ClearUsernamebinding?
The client is sending the hash (password), nonce and created elements in the usernametoken element in the soap headers, but the validation (from the class extending UserNamePasswordValidator) is not reached. The service is being hit anyways because I can set break points in the Application_BeginRequest.
The request from the client is correct, but the service response returns : An error occurred when verifying security for the message. As I said, when the password type is PasswordText, the UserNamePasswordValidator validation is hit, and it works fine. The clients are all Java clients, so I can not use the out of the box options in WCF. Can you point me out where to look at ?
Thanks in advance

Yaron Naveh said...

Anonymous

WCF does not support digest out of the box. I haven't worked with it as well so these are just my thoughts.

The "cleanest" way is probably to create custom token serializer, for example:

http://msdn.microsoft.com/en-us/library/ms731872.aspx

This is a little complex since you need to implement a lot of classes.

There are various of other security extensibility points which not with all I'm familiar. Maybe there is a point where you also have access to the message and you can manually do the validation. I would also ask this in the MSDN WCF forum.

Of course the "brute force" way is to not use WCF security at all and build your own custom channel to do the validation.

Anonymous said...

Great Article, but here is where I am running into issues. To start off, here is what I am trying to do:

I need to build a WCF Web Service with X.509 Certificate and with a Custom WS-Security Token. The reason for the token is to identify if the client can access the webservice. I looked at the MSDN Custom Token article and it works great with a WCF client but I need to build the service keeping in mind there could be a java client consuming it.

So, looking at your article, I wanted to get something simpler than the MSDN token (around 12 classes), but when I made my service an IIS WebService and modified the config files on the client and server, I get an error invoking the client

at System.ServiceModel.ClientBase`1.InitializeChannelFactoryRef()
at System.ServiceModel.ClientBase`1..ctor()
at TestUsernameClient.ServiceReference1.Service1Client..ctor() in C:\Temp\TestUsernameClient\Service References\ServiceReference1\Reference.cs:line 96
at TestUsernameClient.Program.Main(String[] args) in C:\Temp\TestUsernameClient\Program.cs:line 14


Any suggestions ?

Thanks,
Mayur

Yaron Naveh said...

Anonymous

I don't think ClearUsernameBinding exactly fits your situation. It is merely a mean to avoid SSL with usernames.

As for your error, it really depends on how you changed the config. Any change must be backed up with an equivalent change in the config reader classes.

Mandar said...

Yaron,

Thanks for your piece of code.It works absolutely fine.

But when I tryied to set ReaderQuotas property of TextMessageEncodingBindingElement in ClearUsernameBinding.cs class like this :

>>>>>>>>>>>
TextMessageEncodingBindingElement tm = new TextMessageEncodingBindingElement();
tm.MessageVersion = this.messageVersion;
tm.ReaderQuotas = myVariable;
res.Add(tm);
<<<<<<<<<<<<

it came up with error :

Property or indexer 'System.ServiceModel.Channels.TextMessageEncodingBindingElement.ReaderQuotas' cannot be assigned to -- it is read only

It looks like ReaderQuotas can not be set via c# code.

Can it be done through Code?

(btw, I am on .NET 3.5 )

Thanks once again for your help

Yaron Naveh said...

Mandar

You cannot set the ReaderQuotas as a whole but you can set specific elements of it e.g. tm.ReaderQuotas.SomeProperty

Mandar said...

Yaron,

Thanks.It worked.

But it would be great if these readerQuotas values can be set in web.config inside :

>>>>>>>>
< clearUsernameBinding >
< binding name="myClearUsernameBinding" messageVersion="Default" >
< readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/ >



<<<<<<<<<<<<<

Can you guide me to correct resource to do same?

Thanks once again.

Yaron Naveh said...

Mandar

Just follow what I do in code with the "messageVersion".

khaled said...

this do not work on iis7
i try it butnot work throw exception

Yaron Naveh said...

khaled

what error do you get?

Jan Milter Ehlers said...

Hi Yaron
I have tried adding the MaxStringContentLength property to the code, but wcf does not seem to care. I can debug it, and see that it is set to the correct value from my config file, but I still get the error.

I have posted my solution files attached to this issue on your google code homepage.

Yaron Naveh said...

Jan

You set the MaxStringContentLength on a TextMessageEncodingBindingElement, but you do not add this element to the BindingElementCollection rather you immediatelly create another encoding element and add it instead.

Jan Milter Ehlers said...

Thanks for pointing that oversight out, Yaron.
That did the trick.

Regards, Jan

Frank B said...

Is it possible to use the clearUsernameBinding only on the server and then connect to it without any custom binding on the (WCF) client?

I've tried to connect with a basicHttpBinding with security mode set to "TransportCredentialOnly" and the
message clientCredentialType to "UserName", which I think should do the plain username/password combination. Then the service has a messageVersion of "None" on the binding. But I'm getting "An error occurred when verifying security for the message" as well.

I've tried lots of other combinations of these configuration settings but none of them seem to work...

Thanks for any insight!

Yaron Naveh said...

Frank

This is not possible. If it was possible then clearUsernameBinding would not be required at all since every client binding can also be used on the server.

You can use TransportCredentialOnly on both sides if it is what you need.

Frank B said...

Thanks for confirming Yaron. What I actually need is just a simple WCF service with username/password authentication but I cannot rely on certificates or SSL. And I don't want to put restraints on the client (such as having to use your binding).

So if I switch everything in your sample to use just basicHttpBinding with TransportCredentialOnly and message clientCredentialType "UserName" then I can call the service allright but it doesn't authenticate the user: your username validator isn't called and the identity on the thread is not authenticated.

Any clue if this is at all possible (again, without certificates or SSL)?

Yaron Naveh said...

Frank

In TransportCredentialsOnly mode the credentials are in the transport level, whihc means the authentication is done a the iis level and not your validator. If you ant you can configure your iis for that.

Another option is to create a dummy ssl certificate and use it. Your clients will need to cancel the ssl validation error though.

Finally you can ignore the ws security stuff all together and add user/pass fields to each method and authenticate it by yourself.

A vanilla flavour Wcf client cannot use the Wcf infrastructure to send unsecured user/pass at the message level.

Слава said...

Hello!
thank your for suggested solution, but I was confused with one issue. WCF service in project where I used this binding requires session, so I added ReliableSessionBindingElement to BindingElementCollection created in method CreateBindingElements(). After this changes I begun receive a TimeoutException when client tryes to call any service method.

Do you have any ideas why this exception occurs?

Yaron Naveh said...

Слава

Try to setup Wcf trace+log on the server to see if any messages were sent at all and if the server specifies any certain message.

I would advise to initially make the scenario working using the defautl wcf settings (e.g. https and not http so you do not need clearUsernameBinding). Then if this works move to clearUsernameBinding.

Слава said...

When I analyzed wcf service trace I inspected that ReplyTo element of incoming message is


http://www.w3.org/2005/08/addressing/anonymous


So I think it is the issue - service cannot address outgoing message to client after message processing (action is succesfully processed by WCF service, I have run it in debug). In binding I use message version Soap12WSAddressing10 both in client & server configurations. But I cannot understand why this situation occurs.
I will appreciate you for any help. Thanks.

Yaron Naveh said...

Maybe this is the "Service level" debug message trace. Look at the "Transport level" trace to see how it really looked like, or use a tool like Fiddler. Turn on trance (not only log) on both client and server to see exact problem.

Слава said...

Hello again, Yaron.
Is it possible to use this scenarion with wcf duplex callbacks?
i've tried to add CompositeDuplexBindingElement to BindingElementCollection and the exception
"The binding for the contract is configured with an authentication mode that requires transport level integrity and confidentiality. However the transport cannot provide integrity and confidentiality." is occurs.

Yaron Naveh said...

Слава

In AutoSecuredHttpSecurityCapabilities.cs try to return true to all capabilities

Suresh Jakka said...

Hi Yaron,

Thank you for providing the nice way to send username and password to the server without SSL.

I have a desktop app that consumes my service. At the desktop project, when I add the service with clearusernamebinding, it did not add this binding in app.config file. How do I get it in app.config file?

Next, I have a Silverlight app that is also consuming my services. Can I use your binding in Silverlight?

N
Thank you,
Suresh.

Yaron Naveh said...

Hi Suresh

As for the desktop application, the client needs to manually configure clearUsernameBinding as done in the sample console application. The reason is that the clearUsernameBinding dll is not part of .Net 3.5 and needs to be deployed on the client side.

As for Silverlight, I don't see anyr eason why you cannot use this binding, but I haven't really tried that.

Suresh Jakka said...

Hi Yaron,

I tried using the clearUsernameBinding in Silverlight project. First, I cannot add the clearUsernameBinding assembly to silverlight project as reference. Next I tried to build assembly as Silverlight library and I could not get some of the classes from the framework as Silverlight has a compacted version of CLR and in that some of the classes used in clearUsernameBinding is missing. Any ideas/thoughts how to use it?

Thank you for your help,
Suresh

Yaron Naveh said...

Since you're writing the client side the easiest is probably manually inserting the user/pass header into the soap message using a message inspector.

Suresh Jakka said...

Thank you for your quick reply. Could you please provide me any pointers on how to insert username token in outgoing messages?

Thank you,
Suresh

Yaron Naveh said...

You have two missions here:

1. know how to add a custom header
2. know what custom header to add

For the first mission read about message inspector. I hope these are available in SL.

For the second message use a non SL client to send some username with clearusername binding. Then use a tool like fiddler to see how the soap header looks like.

Suresh Jakka said...

Hi Yaron,

Thank you for your reply. I am adding UserNameToken with the help of SilverlightMessageInspectorBinding and it works great now.

Thanks a lot for all your help,
Suresh

Yaron Naveh said...

Suresh

Happy to hear it worked out.

Anonymous said...

Thank you for the article.

How to turn on message signing in your sample code, using some kind of shared secret?

Yaron Naveh said...

You will need to impelement a custom token and add it as endorsing token.

Anonymous said...

This is the first example really worked for many guys up here. Very good article I didn’t see anywhere like this. Thank you very much. After googled 1000 times then my brain started getting it little by little. Now I stated having sleepless nights because of rising questing. Could you please provide me some answers at you leisure?
I want to secure my service with minimum cost/effort.
Here is my environment.
Client/ Server are running on dot.net framework 3.5
WCF hosing on XP / IIS
SSL on XP/IIS server side only, not on the client machines because I am having too many (20 to 30) clients I do not want to install client certificate for all of them instead they will use username password at message level. My clients are scheduled dot.net console programs (non GUI).

1. If I create my own server certificate then how to bypass the run-time exception (trust) at client program.
2. How to avoid creating client certificate and taking advantage of SSL. (support many number is anonymous clients with userid and password) ? Encryption at transport level and username password at message level is good enough.
3. What are the suitable configuration settings (binding etc).
4. If I decided to use AspNetMembership..authentication with HTTPS do I need to generate client certificate and how to implement?

Please let me know if my questions are not clear?

Yaron Naveh said...

If you need to protect the information (encrypt it) then ssl is the answer. You would have to have a certificate which the clients consider valid, or whoever wirtes the client will need to hard code it.

If you need authentication then username/password should work.

In short, I don't see why you cannot use the basicHttpBinding with security mode TransportWithMessageCredentals (or even just Transport). You should check the WCF SDK samples of these scenarios.

kaison said...

I got your code working, but when I look at the outgoing request SOAP message, it has weird "o"-headers (and "s"-headers, like this:

POST http://cdab7040:8080/axis2/services/WarrantyClaimService HTTP/1.1
Content-Type: text/xml; charset=utf-8
VsDebuggerCausalityData: uIDPoyjNuCOX2IxGkPhHdTsHCxMAAAAAqH2I7rGrDUK7WgT+/UrjachdWkhvqlRHtnt+Xx5ymrMACQAA
SOAPAction: ""
Host: cdab7040:8080
Content-Length: 947
Expect: 100-continue
Connection: Keep-Alive

2010-03-08T15:21:44.050Z2010-03-08T15:26:44.050Zapaapa625231234567EU12007-01-0112345678

I want to be able to make a SOAP request to an Axis webservice with wsse- username credentials in cleartext, something like this:

User Name HerePWD HEREJFVPJvzLlwpgc31cYOhMmQ==2009-03-26T14:04:01Z



12345
8765624
FI
1
2008-01-10
1111





Is this something I can accomplish by modifying your code? (Unfortunately WCF won't allow me to do this out of the box.)

Yaron Naveh said...

kaison

The xml did not came well in the comment. Please send it to my personal mail and I will answer you.

Suresh Jakka said...

Hi Yaron,

How can we use this binding to do duplex communication in Silverlight? I mean, like pollingDuplexHttpBinding.

Any ideas is greatly appreciated.

Thank you,
Suresh

Yaron Naveh said...

Suresh

you would need to create pollingClearUserNameBinding. In the createBindingElements section it would need to create the same elements as pollingDuplexHttpBinding uses. You can use the reflector to see these elements. Then you would need to replace the httpElement in the autoSecuredHttpTransportElement from the ClearUsernameBinding code.

Suresh Jakka said...

Wow...I really appreciate your quick response. I will try to create polling duplex version of clearUsername bidning.

Jinn said...

Hi Yaron,

It's a very interesting approach you are doing here. I've tried to use it and haven't got the right result yet.

I am building some kind of backoffice module where I need to send a Soap Request to an Oracle Webservice written in Java (as far as I can see). The request needs to include credential data, and it's http://...

I'm trying to use WCF, and yours is so far the only suitable solution for this scenario.

I have the following error after using ClearUsernameBinding:
'http://JP420000.bssv.e1.oracle' contract is configured with an authentication mode that requires transport level integrity and confidentiality. However the transport cannot provide integrity and confidentiality.

Do you have any idea what's going wrong here?

Any other suggestion is much appreciate.

Thanks,

Tuan Jinn

Yaron Naveh said...

Jinn

When you use the sample project from the binding sdk, does it work?

If so then I assume the issue is a wrong configuration, you can publish here your configuration.

Yaron Naveh said...

Jinn

When you use the sample project from the binding sdk, does it work?

If so then I assume the issue is a wrong configuration, you can publish here your configuration.

Jinn said...

Hi Yaron,

My apology for being late, I was watching Barca vs. Inter. What a disappointing game.

Well here is my client config, please note that this client stays behind a proxy, so to communicate with the service I have to bypass them too:
----------------------------------------------------------------


















-----------------------------------------------------------------
And I have tried to config it in my code:
var proxy = new WCFClientWhatever.Oracle_E1_SBF_SEI_PkgBldFile_TEST("test");
proxy.ClientCredentials.UserName.UserName = "wow";
proxy.ClientCredentials.UserName.Password = "ineedholiday";
BindingElementCollection elements = proxy.Endpoint.Binding.CreateBindingElements();
var transportSecurity = (TransportSecurityBindingElement)elements.Find();
transportSecurity.IncludeTimestamp = false;
//*****I have tried all kind of settings here for the transport security

proxy.Endpoint.Binding = new CustomBinding(elements);
var response = proxy.RunSomething("too bad");

Do I miss something here??? Again the error is:
blah blah 'http://JP420000.bssv.e1.oracle' contract is configured with an authentication mode that requires transport level integrity and confidentiality. However the transport cannot provide integrity and confidentiality'

Thank you for your time
Tuan Jinn

Yaron Naveh said...

Jinn

Do you use clearusernamebinding in your code? It seems like you are using the ootb settings.
If you do use CUB then verify the demo works and see hwo your code is different.

Software said...

Thanks for this Post!

How can we address the WSDL publishing issue associated with offloaded ssl?

For example, using your binding our service is hosted behind our F5 at http://myInternalServer/myApp. I'd like the WSDL to state its publich address however, https://myPublicServerName/myApp. I can use the F5 to strip the SSL and redirect, and your binding to handle the username credential, but it doesn't solve the address publication issue.

Any thoughts?

Yaron Naveh said...

Hi Software

Try to set the listenUri property in the endpoint configuration to the address the wsdl should be on (http://myInternalServer/myApp?wsdl) and the "address" property to https://myPublicServerName/myApp

Anonymous said...

Hi, Yaron:

I am having difficulty getting it work for WCF service hosted in IIS, VS2008 default server. here is my configuration for service:

Yaron Naveh (MVP) said...

Hi Anonymous

The comments do not show well xml. You can send it to my mail. Also specify the errors you get, and if you are able to run other wcf services on the server.

K said...

Here is a solution for "The maximum message size quota for incoming messages (65536) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element.". You'll need to download the source code and make the following changes:

class ClearUsernameBinding
{
...
private long maxReceivedMessageSize = 65536;

...

public void SetMaxReceivedMessageSize(long value)
{
this.maxReceivedMessageSize = value;
}

public override BindingElementCollection CreateBindingElements()
{
...

res.Add(new AutoSecuredHttpTransportElement() { MaxReceivedMessageSize = this.maxReceivedMessageSize });

return res;
}
}



class ClearUsernameBindingElement
{
...

protected override void OnApplyConfiguration(Binding binding)
{
ClearUsernameBinding b = binding as ClearUsernameBinding;
b.SetMessageVersion(MessageVersion);
b.SetMaxReceivedMessageSize(Convert.ToInt64(MaxReceivedMessageSize));
}

...

protected override ConfigurationPropertyCollection Properties
{
...

properties.Add(new ConfigurationProperty("maxReceivedMessageSize", typeof(string), "65536"));
}

...

public string MaxReceivedMessageSize
{
get
{
return (string)base["maxReceivedMessageSize"];
}
set
{
base["maxReceivedMessageSize"] = value;
}
}
}


Finally in your web.config or app.config, you can now add maxReceivedMessageSize="5000000" as follows:

Gerwin Postma said...

Hi Yaron,

Thanks for making this possible. I had to use your classes to meet the requirements of sending UN/PW over HTTP. I couldnt het a PasswordDigest to work, until i found the work of aszego (UsernameToken). With this i was able to send WSE headers and an encrypted (Digest) PW.
Please check the posting (raw..) here http://developer.web-log.nl/log/2010/08/wcf-http-with-passworddigest-and-then-some.html

Yaron Naveh (MVP) said...

Thanks Gerwin. I've published a post linking to this (and to your blog).

Anonymous said...

Links to the source code are giving 404.

Yaron Naveh (MVP) said...

Fixed

Sponge_Bob said...

Great Work. Impressive to say the least. I do have a question though.
I implemented you "Clear Username Binding" into my project. I can get to work for simple things but I am syncing my client database using WCF and Microsoft Synchronization. The syncing works fine if I am using wsHttpBinding but when I use clearUsernameBinding I get "The maximum message size quota for incoming messages (65536) has been exceeded." I had the same issue previously with wsHttpBinding but was able to increase MaxReceivedMessage and other related attributes on wsHttpBinding.
How can I add the necessary attribitues to clearUsernameBinding.

Ps I would also like to use reliableSession with clearUsernameBinding. Is it possible to do these things?

Thank you for putting all the work into this.
Paul

Yaron Naveh (MVP) said...

Hi Bob

Search MaxReceivedMessage in the comments to this post, some of them eal with it. Basically you need to add one line to the binding code (as a quick solution) or can define it in a way which would allow to set this in the config xml.

reliableMessaging is also possible. in ClearUsernameBinding.cs in CreateBindingElements() just add this:

res.Add(new ReliableSessionBindingElement());

(not sure if you need to add it before or after adding the security).

There is also a code less way to do it but the code is actually easier here.

Sponge_Bob said...

Wow, Thanks so much for the quick response. I will try this when I get home from work.

Sponge_Bob said...

Hi again Yaron, Thank you so much for your help. I have the syncing of the database working now except for usage with reliableSession. I add res.Add(new ReliableSessionBindingElement()); as you suggested.

I get this error whenever I try and sync while using reliableSession
InnerException: System.ServiceModel.ProtocolException
"Addressing Version 'AddressingNone (http://schemas.microsoft.com/ws/2005/05/addressing/none)' is not supported."

I googled this error but am not finding anything useful other than vague mention of Version issue. Do you know any work around or fix for this.

Thanks again,
Paul

Yaron Naveh (MVP) said...

Paul

In app.config instead of "Soap12" use message version Soap12WSAddressing10.

Sponge_Bob said...

Thanks again Yaron Soap12WSAddressing10 worked Perfectly. I really don't know how to thank you enough. So I guess I will just say it.

Thank YOU,
Thank YOU,
Thank YOU...

Paul

pbred said...

Yaron,

First thanks for all the replys you have made to the various posting questions. I've used themt to work through several issues. In the past I have been depolying to a Windows 2008 Server using IIS 7. Today while trying to deploy the same webservice on Windows Server 2003 with IIS 6 I ran into some issues. I turned on using the service trace viewer I tracked the error back to the following message. What is really throwing me off is the fact that I can navigate to the wsdl and see it just fine, but can't complete a call.

"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."

Just for testing purposes I stripped out the ClearUserName binding and was able to get the service to run. Any thoughts or ideas would be appreciated. My first reaction has been that I don't have some setting correct in IIS 6.

Thanks in advance for any help.

-Phil

Yaron Naveh (MVP) said...

Hi Phil

Usually iis settings are not required for CUB.
Maybe the client is configured in a different way?

Turn on wcf logging on the server side and see how the client message looks like. Maybe the client is not configured to send a username.

pbred said...

Yaron, Thanks for the quick reply. I am pretty sure the security header looks correct in the message.
<<<<<<<<<<<<<



2010-09-22T21:28:58.039Z
2010-09-22T21:33:58.039Z



fakeuser
faksepassword


>>>>>>>>>>>>>

Yaron Naveh (MVP) said...

Xml does not appear well in comments - send it to my mail.

Dan said...

Hi Yaron,

I'm using the ClearUsernameBinding, and its working and looks like it could be a great time saver and development tool. But, during the first execution of method from the proxy I'm getting an error "Unable to automatically debug 'Service'."

This is within a WCF Service Application project type, and the service is accessed through a service reference in winform client. Debugging is enabled on the client, as well as debug="true" and includeExceptionDetailInFaults="true" on the service.

The other issue is that when the service reference is updated, the automatically generated code breaks the web.config. It sets up a new custom binding that doesn't communicate with the service.

I was just wondering if you've come across these issues and if you could help me move past them.

Thanks!

Yaron Naveh (MVP) said...

Hi Dan

The first issue seems a web service debugging issue. It shoul dnot happne when you run the application without debugging. In order to debug the service on iis should have debug symbols and you should attach to iis. Or does this happen with the shipped console demo?

As for the second issue, the only way out (for now) is to ignore the config and do it from code:

var b = new ClearUsernameBinding()

and then give it in the proy ctor.

Eddie Wassef said...

Hey Man,

First of all, this is fantastic, thank you.
I have a scenario where i need to use the membership provider for username and password authentication over WCF but the transport security will be handled by the load balancer.
So, the server side needs to think and act as if it is basic http with user name and password credentials.
But when the client connects to the service over the internet, it is https for all intensive purposes.
I have your binding configured on both sides but the client refuses to allow an address with an https...

help....

Yaron Naveh (MVP) said...

Hi Eddie

In this case you only need CUB on the server side.

Dan said...

Hi Yaron,

Thanks again for all your responses.

One of the common questions seems to be quotas that have been exceeded. I too experienced the MaxReceivedMessageSize error, but was able to resolve the issue using the example provided earlier in the comments (and can set this value in the web.config).

My next concern is that I am receiving this error for maxArrayLength. I have tried to set it similarly to the maxReceivedMessageSize property, but have so far been unsuccessful. I am even trying to initialize the binding (within ClearUsernameBindingElement) with the maxArrayLength preset to a higher value.

For example the following line returns a null value exception:

properties.Add(new ConfigurationProperty("maxArrayLength", typeof(XmlDictionaryReaderQuotasElement), "2147483647"));

Any help on how to properly set this value would be greatly appreciated.

Thanks!

Dan said...

Actually I've ended up realizing my problem in that these values needed to be set in the clearusernamebinding class itself inside of the TextMessageEncodingBindingElement object. One gotcha was that it didn't like being initialized with the values of readerquotas, but when i set it seperately it worked fine, like:

TextMessageEncodingBindingElement textElement = new TextMessageEncodingBindingElement();
textElement.ReaderQuotas.MaxArrayLength = this.MaxArrayLength;
textElement.MessageVersion = this.messageVersion;

var res = new BindingElementCollection();
res.Add(textElement);

Jan Milter Ehlers said...

Hi Yaron

I have the same problem as Alex namely "The element "bindings" has invalid element 'clearUsernameBinding'. List of possible elemnts expcted: 'basicHttpBinding'...". The error is present when I hover over the section in web.config. This is also present in you sample. It will indeed run, but I cannot use visual studio to add any services to the project. When adding a service to the project I get an error message that says that visual studio cannot load file or assembly 'ClearUserNameBinding' or one of its depencies. The same holds true, when it add a WCF-service project to the SDK solution and try to add a service to that.

Yaron Naveh (MVP) said...

Hi Jan

Are you trying to build a client or a service application?

If you build the service w/o CUB and after the skeleton is ready switch to CUB does it work? this should run in the same way the sample does.

Jan Milter Ehlers said...

Hi Yaron

To answer your questions, yes it is a server project, and yes it works if I add the service first and then add CUB afterwards. It will build and run, but Visual Studio will show the error when I hover over the binding in the config file. The funny thing is that visual studio is able to find the dll in the extension declaration, but not in the binding declaration.
I use Visual Studio 2008. Perhaps CUB needs to be registered in GAC, or be present the special Visual Studio Program Files directory?

Jan Milter Ehlers said...

Hi Yaron

I found an explanation. It is a known error. The solution is to put CUB in the GAC or in the VS program files directory.
See http://stackoverflow.com/questions/169342/why-isnt-my-custom-wcf-behavior-extension-element-type-being-found

Jan Milter Ehlers said...

Hi Yaron

I tried the workaround from Microsoft stated in my earlier post. I did not work, but I guess the conclusion is that this is a known error in Visual Studio. It just puzzles me, that you have not run into it yourself.
/Jan

Yaron Naveh (MVP) said...

Jan

I do get the warning in the config file when I hover over the element.

Also I can edit the web.config only if the CUB assembly is copied to the config folder.

I do not have problems to find the CUB assembly in runtime.

venky said...

Hi Yaron,

I am trying to consume a java based web service which requires security headers in the request over HTTP. Something like this:





xxx
xxx
uZcEd8k71DYcwxMSM7i53A==
2011-02-12T08:40:08.843Z




....




Is it possible to create a WCF client to invoke a service which requires such security over HTTP. I tried using ClearUsernameBinding but got an error which says "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."

Please help.

Yaron Naveh (MVP) said...

Hi Venki

take a look at:

http://blogs.msdn.com/b/aszego/archive/2010/06/24/usernametoken-profile-vs-wcf.aspx

venky said...

Hi Yaron,

Thanks for the reply. There is an issue with the code in that post. The TransportSecurityBindingElement sets the property AllowInsecureTransport to true so that Username token is transported over HTTP. But this property is available in .NET 4.0 and i am using VS 2008. If i comment this line and run the sample it gives me an error saying:
"The request failed with unexpected exception: System.InvalidOperationException:
The 'CustomBinding'.'http://tempuri.org/' binding for the 'IEchoService'.'http:/
/tempuri.org/' contract is configured with an authentication mode that requires
transport level integrity and confidentiality. However the transport cannot prov
ide integrity and confidentiality."
Moreover there is a hotfix KB971831-http://code.msdn.microsoft.com/KB971831 available for NET 3.5, but the link gives a .msu file to download for the fix which targets Vista machines and i am working on XP.
Is there any solution for that property?

Anonymous said...

Great work Yaron..!
Really appreciate your work.

Yaron Naveh (MVP) said...

venky

you would need to "integrate" CUB with the article in that post. You are facing two issues (clear username, username format) and only the combinations of both projects will work.

Massimo Bonanni said...

Hi, Yaron
I try to use your library to call a Java WebService implements WSS Username Token Profile 1.0 (the ws developers said me that it was implemented using AXIS2 and Rampart).
It doesn't works because, in the header there is Timestamp tag:

<u:Timestamp u:Id="_0">
<u:Created>2011-03-21T12:27:14.576Z</u:Created>
<u:Expires>2011-03-21T12:32:14.576Z</u:Expires>
</u:Timestamp>

Can we remove it from the request?

Thank you so much (specially for good job)!!!

Massimo boanni said...

Hi, Yaron.
I resolved my timestamp problem using IncludeTimestamp on SecutityBindingElement.
Sorry for the comment.

Max

Comunidade Barbara said...

This solution works on IIS?

Yaron Naveh (MVP) said...

yes

Anonymous said...

Could someone post a sample of how to use netTcp with ClearUsernameBinding?

Steven said...

I applied the changes mentioned in previous posts for net.tcp and I get the exception:

The HttpGetEnabled property of ServiceMetadataBehavior is set to true and the HttpGetUrl property is a relative address, but there is no http base address. Either supply an http base address or set HttpGetUrl to an absolute address.

Yaron Naveh (MVP) said...

Steven

this error seams unrelated to CUB - you can remove CUB and will probably get the same exception. If you want the metadata (wsdl) to be over http add an http address to the base addresses.

Steven said...

Yes, correct. Got past that exception but I'm having other problems. We have the strange case of not being able to use Windows auth or certificates. We have an intranet setup and so would prefer to use TCP/binary services (old fashioned client-server). Session support would be nice too.

Yaron Naveh (MVP) said...

Steven

If you use windows auth / certificates then CUB is not relevant. The problem relies elsewhere.

For windows auth check that you can get it to work with http first and that client and server are on the same domain. For x.509 check any errors you may see in trace logs.

Holly Styles said...

Hi Yaron,

I am exactly in the position that your ClearUsernameBinding solves. My client has a load balanced SSL appliance in front of a web-farm.

I have played with this in my test environment and all is fine over http. But if I set the endpoint address in my client to https to go via the balancer I get an error:

The provided URI scheme 'https' is invalid; expected 'http'. Parameter name via

I'm confused about whether the client should be using ClearUsernameBinding as well or the usual wsHttpBinding ? I presumed ClearUsernameBinding would be happy with either protocol. Please help I am feeling dumb.

Can you help

Isaac said...

Fantastic post! It helped me get a java client into a wcf service working.

I am still struggling with getting my service to stop calling UserNamePasswordValidator.Validate with every service method call.

The service still works, but it calls my user authentication service with every call. wsHttpBinding works and it only calls UserNamePasswordValidator.Validate once.

I am using VS2010, WCF4, .NET4.

Has anyone had any luck with that?

Thanks.

Axi said...

I can't get it run on IIS7.
I get the following error (does not dependent on the credentials):
"An error occurred when verifying security for the message."
The only difference in my web.config to your app.config is the endpoint address set to empty string.
I also can't debug into the wcf-Service anymore.
Can you try it hosting on wcf and sending me an example!
thx
©a-x-i

venky said...

Hi Yaron,

I used the Username format as described in the other blog and everything seems to work fine untill it calls the method exposed by the service. It throes the error: "Failed to route event via endpoint: null. Message payload is of type: ".
I enabled message logs and the message shows that the security token was passed in the soap header alongwith the soap body as follows:


5c83febc-da68-49d1-92cf-fc404a933b16











2011-04-14T10:09:32Z




This means the request is passing the WSE security but what is the solution for the endpoint error? Please help

John said...

Have tested with the posted solution. My server side (WebSphere JAX-WS SOAP 12) works fine with no error. But the client side (WCF) gives error as below:

System.ServiceModel.Security.MessageSecurityException was unhandled
Message="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."
Source="mscorlib"
StackTrace:
Server stack trace:
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.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at HelloWorldMediationServiceClient.ServiceReference.HelloWorld.callHello(callHelloRequest request)
at HelloWorldMediationServiceClient.ServiceReference.HelloWorldClient.HelloWorldMediationServiceClient.ServiceReference.HelloWorld.callHello(callHelloRequest request) in C:\Users\SLI\Documents\Visual Studio 2008\Projects\HelloWorldMediationServiceClient\HelloWorldMediationServiceClient\Service References\ServiceReference\Reference.cs:line 223
at HelloWorldMediationServiceClient.ServiceReference.HelloWorldClient.callHello(callHello callHello1) in C:\Users\SLI\Documents\Visual Studio 2008\Projects\HelloWorldMediationServiceClient\HelloWorldMediationServiceClient\Service References\ServiceReference\Reference.cs:line 229
at HelloWorldMediationServiceClient.Program.Main(String[] args) in C:\Users\SLI\Documents\Visual Studio 2008\Projects\HelloWorldMediationServiceClient\HelloWorldMediationServiceClient\Program.cs:line 23
at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:

Yaron Naveh (MVP) said...

Holly

If the client calls an ssl endpoint it does not need to use CUB. Only the server would need.

Yaron Naveh (MVP) said...

Isaac

How would you like further calls to be authenticates? This is typically done with secure conversation which would require certificates which is what you try to avoid anyway.

What you could do instead is use the asp compatability mode and issue cookie to the client. In this case it might be best not to use CUB but simply have the user/pass in a custom header.

Yaron Naveh (MVP) said...

Axi

Do you use iis as service or client?
Try to turn on WCF trace. Also you can write to file from your username authenticator to see if it is called at all.

Yaron Naveh (MVP) said...

venky

it is hard to put xml in comments - please sent it to my private mail.

Yaron Naveh (MVP) said...

John

Please find how the reposne looks like (e.g. with fiddler or WCF logging) and send it to my mail. possibly this is a different issue due to something in the response. If the response is an error (Fault) then check how the request differs from a working sample

Isaac said...

Thanks Yaron.

If CUB must call UserNamePasswordValidator.Validate every method call, is there another approach that doesn't involve certificates but still calls UserNamePasswordValidator.Validate once?

I really like the CUB approach because my service and UserNamePasswordValidator.Validate can stay the same regardless of the secure or non-secure binding.

I was hoping for a way to modify the CUB classes to support this like a ReliableSessionBindingElement (which didn't work for me).

Yaron Naveh (MVP) said...

Issac

I don't think there is a way. The client would need not to send the username the second time but some token so that the server would identify it. The only standard token is the secure conversation which I don't see how you can do w/o cryptographic material.

you could use asp compatability mode but then you would need to handle the auth yourself.

note it's not only the server side that your requirement affects but also the client should know not to send username the second time.

Anonymous said...

Code.goole gives a message for ClearUsernameBinding unavailalbe

Yaron Naveh (MVP) said...

this was probably a glitch - works fine now

clopatofsky said...

Yaron

Greetings from Bogotá, Colombia, I am using your ClearUsernameBinding solution for and VSTO Addin for Excel 2010, this implies that the messages usually contain big amounts of data and I've been trying to increase the ReaderQuotas programatically to the TextMessageEncodingBindingElement with no result. How can I configure this custom binding correctly both in client and server with readerquotas greater than custom values?

Thanks for sharing your valuable work.

Yaron Naveh (MVP) said...

Hi Carlos

What error do you get?
Can you share the code you tried?

Anonymous said...

i getting follwoing error
when i used this approcach..
The maximum message size quota for incoming messages (65536) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element.

Yaron Naveh (MVP) said...

Anonymous

Look in previous comments to this post about this error and my response to them on how to solve it.

frymi said...

Hi,

I'm using your ClearUsernameBinding on my client(WCF client on .NET 3.5) to connect to servis which require UserToken over http. Server use Soap 1.1 so I configure client to use it {messageVersion="Soap11"}.

I'm getting MessageSecurityException: 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)

How to resolve that problem ?


Best regards,
frymi

Yaron Naveh (MVP) said...

Hi frymi

Possibly the server returns a username token in the response? This is not standard but I have seen it. turn on WCF logging or Fiddler to find out.

If so then I recommend you build a custom message inspector which strips this token out of the message b/c WCF as a client cannot handle it.

Silvio Ferreira said...

Hi Yaron

When I use ClearUsernameBinding and try to return a great number of objects in a search method, I get the following error:

"The maximum message size quota for incoming messages (65536) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element."

ClearUsernameBinding has no such attribute. Is there a solution for this problem?

Yaron Naveh (MVP) said...

hi Silvio

search this error in previous comments, I have replied to them with an example.

Anonymous said...

Hi
I have to do some what same , My message headers will contain the user name and password , which i have to validate and provide a token to the user next time i have to validate the token and also check if the token is not expired..Also there can be anonymous user for them as well i have to provide a token and check expire date and time in next request, can you please suggest me how to do this...

Carlos Chicas said...

Hi,

Can I consume this webservice with PHP?

If the answers is yes, how?

Yaron Naveh (MVP) said...

Carlos

I assume that yes, but I have not tried. This may help:

http://www.dimuthu.org/blog/2008/09/23/authenticate-using-username-token-from-php-2-minutes-introduction/

Elias said...

Hello!

Great article and great work!

I wonder, is there any way to manually construct a Security header that will be accepted by a service using the ClearUsernameBinding?

I'm trying to make a call from an Android device, using the library ksoap2-android to construct the envelope and perform the call, etc. Of course there is no built-in support in ksoap2-android for the ClearUsernameBinding, so I've been trying to construct the header myself, but I keep running in to trouble. The service just won't accept my request!

This is the header that I'm sending:



2011-09-27T12:49:32Z
2011-12-31T00:01:01Z


struts
R1I8/N/Cavs=



I've used Wireshark to inspect the contents of the request and response from your test client and test server respectively and tried to replicate them.

When I perform the request, however, I get this error message on the service: "ArgumentNullException: Value cannot be null. Parameter name: actors".

Do you have any idea of how to solve this? It'd be great!

Thanks in advance!

Yaron Naveh (MVP) said...

Hi Elias

Xml does not appear well in comments so you can send it to me in an email.

Possibly the request contains actor="" which wcf does not like? can you remove it?

Also turn on wcf trace to see if there is any inner exception. You can also compare the non-working request to some working one.

qingshui.go said...

HI,Yaron
When I tried clearusernamebing in my WCF which marked as AspNetCompatibilityRequirementsMode=required, then it will get MessageSecurityException, the message like"Negotiate,NTLM", Do you know how to handle this exception?

PS:in IIS the allow Anonymous and Integrate windows Authen

Yaron Naveh (MVP) said...

qingshui.go

this typically means the server expects transport security and not message. try to call it with basichttpbinding you should get the same exception. CUB is not relevant here (yet).

Try to enable only anonymous auth just to test.

Navin said...

Hi Yaron

I have done exact implementation as you have suggested in the ClearUsernameBinding solution except my AutoSecuredHttpTransportElement class looks like this.

public class AutoSecuredHttpTransportElement : HttpTransportBindingElement,
ITransportTokenAssertionProvider
{
public override T GetProperty(BindingContext context)
{
if (typeof(T) == typeof(ISecurityCapabilities))
return (T) (ISecurityCapabilities) new AutoSecuredHttpSecurityCapabilities();

return base.GetProperty(context);
}

public override BindingElement Clone()
{
return new AutoSecuredHttpTransportElement();
}

public System.Xml.XmlElement GetTransportTokenAssertion()
{
return null;
}
}

I am using following binding in client app config.










The endpoint address is https and I am getting following error

The message with Action '' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver. Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None).

Could you please help.

Thanks.

Yaron Naveh (MVP) said...

Hi Nitin

If the client is https then it should not use CUB.

BIKE said...

Hi Yaron, first of all thanks for this useful post and the code.

I've been using this and it works perfectly with my .net clients. I need to use this also with java and old vb6 clients.

In my scenario I've the same service published with two bindings: one using https and SSL certificate and another one using you custom clearusernamebinding and plain http transport.

The problem is that when I test with SoapUI the service using clearusernamebinding is NOT working, I get a "Bad request" error and the log trace for the service says "There is a problem with the XML that was received from the network. See inner exception for more details."

I'm sending username and password in the soap envelope. I'm kind of confuse with all this.

I think my question is: does your custom binding works with clients other than .net ones ?

Thanks!

Yaron Naveh (MVP) said...

Hi Bike

Please send me how the soapUI request looks like. Possibly the issues is with soap/wsa versions.

I also suggest to turn on tracing on the wcf service to see more info

BIKE said...

Hi Yaron, thanks for your help. I solved my problem with SoapUI; it was a mistake in my soap request, now the service responds to SoapUI requests.

Here is a sample of my soap message (just for reference):

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:tem="http://tempuri.org/">
<soap:Header>
<wsse:Security mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken wsu:Id="UsernameToken-5700630" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:Username>myUsername</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">myPassword</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soap:Header>
<soap:Body>
<tem:Operation1>
<tem:param1>123</tem:param1>
<tem:param2>abc</tem:param2>
</tem:Operation1>
</soap:Body>
</soap:Envelope>

This soap request works perfectly, I get the expected results from the service.

Another question: My .net clients need to reference the dll where I've the custom binding implementation. Will this custom binding still work with java or vb 6 clients; I guess they would since SoapUI does, just a concern that I have.

Thanks!

Yaron Naveh (MVP) said...

great news. yes it should work with other clients

Brian said...

Hi

Thanks for the code sample.

I've run into a problem. Whenever I do an "update service reference", the client app.config configuration gets messed up. The clearUserNameBinding node gets replaced with a customBinding node. Is this expected or an I doing something wrong?

Thanks

Yaron Naveh (MVP) said...

Brian

This is expected since there is no client extension that knows the CUB. As far as "update service" is concerned this is just a custom binding.

Anonymous said...

I have the feeling that on the server, ClearUsernameBinding can only be used in a hosted mode, not when using a "WCF Service" website project started by the ASP.NET development server.

The error I get is

Content Type application/soap+xml; charset=utf-8; action="http://tempuri.org/IEchoService/EchoString" was not supported by service http://localhost:1431/EchoService.svc.

Any ideas how to get it to work with development server?

SAVANT said...

Hi Yaron,

I am really in need of your help.

By looking into your post I created a customBinding. My service config is,






































and this is working fine with SOAP UI tool after giving the UN/Pwd but when I created the client and connecting its throwing me the below error
" MessageSecurityException: 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."

Client config is


























Please help where am I doing wrong. Thanks in advance.


Regards,
Aru

Yaron Naveh (MVP) said...

Hi SAVANT

Use a tool like fiddler or wcf logging to see how the message looks like and how it differes from the working one.

Yaron

venier said...

I'm using your solution in a project. I need to validate access by User, but I also need validate each method.
For example, I have two [OperationContract] and a given User can access the two methods, but another User can only access the first one.
How can I implement this? is there any way in the [OperationContract] that can i get who is the current User?
Or maybe in the method "Validate", of the "UserNamePasswordValidator", get some way to know which one the [OperationContract] that was requested?

thanks in advance.

«Oldest ‹Older   1 – 200 of 243   Newer› Newest»