2

I have a VB.NET (2008) console application which consumes a web service. I originally started writing it using the old/legacy (pre-WCF) technology of importing the WSDL with WSDL.exe (or "Add Web Service" in Visual Studio), which creates classes based on System.Web.Services.Protocols.SoapHttpClientProtocol. However, I soon realized that this not the best way to do it (thanks to John Saunders' comments in my previous question -- How to get serialized XML of object passed to web service?).

So, I've got my code converted over to WCF now (using "Add Service Reference", which creates classes based on System.ServiceModel.ClientBase); and it works more or less the same, except for one key point: security.

The web service I am consuming was written in Java; and while we both (me, and the team who developed the web service) work for the same company, I don't really have much control over how they publish and expose the web service. Their requirement is that I pass the username & password (Basic HTTP authentication) over HTTP, not HTTPS. I know that's not the most secure way to do it; but that's a battle I can't fight right now.

This worked just fine using the old way. But if I try to do this with WCF by setting this in the app.config:

<security mode="Transport">
    <transport clientCredentialType="Basic" />
</security>

... and setting username and password in code like this:

oServiceClient.ClientCredentials.UserName.UserName = "SomeUsername"
oServiceClient.ClientCredentials.UserName.Password = "SomePassword"

I have this exception politely thrown at me:

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

So that sucks; and searching StackOverflow and other sites does not turn up much in the way of getting around this in .NET 3.5. I found thing which I thought might be promising (http://webservices20.blogspot.com/2008/11/introducing-wcf-clearusernamebinding.html); however, it looks like this solution requires config changes on both the service side and the client side. And as previously mentioned, I don't have any control over the server side of this.

Is there any way to accomplish this using a WCF-based client? Or do I need to give up and go back to the old way?

EDIT: I seem to be having some success with this:

<security mode="TransportCredentialOnly">
    <transport clientCredentialType="Basic" />
    <message clientCredentialType="UserName" />
</security>

But this security mode (TransportCredentialOnly) doesn't seem to be referenced in the Microsoft help articles / tutorials. Am I barking up the right tree?

Community
  • 1
  • 1
Marcoid
  • 53
  • 1
  • 7
  • `TransportCredentialOnly` is only available with `BasicHttpBinding`. It's part of the [BasicHttpSecurityMode Enumeration](http://msdn.microsoft.com/en-us/library/system.servicemodel.basichttpsecuritymode.aspx), but they don't have a whole lot of info on it. – Tim Apr 20 '13 at 07:08
  • From the above link: "This mode does not provide message integrity and confidentiality. It provides only HTTP-based client authentication. Use this mode with caution. It should be used in environments where the transfer security is being provided by other means (such as IPSec) and only client authentication is provided by the Windows Communication Foundation (WCF) infrastructure." – Tim Apr 20 '13 at 07:10
  • Also take a look at this SO answer - http://stackoverflow.com/a/1546086/745969 – Tim Apr 20 '13 at 07:12

2 Answers2

2

The solution, in my case, turned out to be setting security mode to "TransportCredentialOnly", like this:

<security mode="TransportCredentialOnly">
    <transport clientCredentialType="Basic" proxyCredentialType="None"
        realm="" />
    <message clientCredentialType="UserName" algorithmSuite="Default" />
</security>

Credit to evgenyl for prompting me to open up my research to other security modes; but in the end, it was "TransportCredentialOnly" rather than "Message" which did the trick.

Marcoid
  • 53
  • 1
  • 7
1

You receive this error, because "transport" security mode suppose https. You can use message security mode. See this post for more info: http://msdn.microsoft.com/en-us/library/ms733137.aspx

evgenyl
  • 7,837
  • 2
  • 27
  • 32
  • Thank you very much for replying, evgenyl. I tried changing the security mode to "Message" like this: – Marcoid Apr 20 '13 at 05:55
  • ... but I get this exception: "System.InvalidOperationException: BasicHttp binding requires that BasicHttpBinding.Security.Message.ClientCredentialType be equivalent to the BasicHttpMessageCredentialType.Certificate credential type for secure messages. Select Transport or TransportWithMessageCredential security for UserName credentials." – Marcoid Apr 20 '13 at 05:57
  • So then I tried setting security mode to "TransportWithMessageCredential", and I was back to the same exception I started with: System.ArgumentException: The provided URI scheme 'http' is invalid; expected 'https'." – Marcoid Apr 20 '13 at 05:58
  • * I seem to be making some headway with "TransportCredentialOnly" security mode setting (please see edited post above). Is this the right way to go? – Marcoid Apr 20 '13 at 06:53