Pergunta

I'm working in a big project that makes extensive use of WCF for different kinds of communication. As a part of a new requirement, we need to communicate with a SOAP Web Service developed by a third party. Their service is developed with Java and has two security requirements:

  1. it needs BASIC authentication over transport and

  2. the message has to be signed (not encrypted) with a X509 certificate using the WS-Security (OASIS) standard for non-repudiation.

The problem I have is that the bindings provided by WCF allow using either transport or message security, but not both at the same time. As a result I can either sign the SOAP message or send BASIC authentication credentials, but so far I haven't been able to do both as I require.

I have been trying to find a solution for days, and so far I have concluded that probably my best shot is to make a custom binding programmatically. Using several sources, this is what I have right now:

var b = new CustomBinding();

var sec = (AsymmetricSecurityBindingElement)SecurityBindingElement.CreateMutualCertificateBindingElement(MessageSecurityVersion.WSSecurity10WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10);

UserNameSecurityTokenParameters tokenParamenters = new UserNameSecurityTokenParameters();
tokenParamenters.InclusionMode = SecurityTokenInclusionMode.AlwaysToRecipient;
tokenParamenters.RequireDerivedKeys = false;

b.Elements.Add(sec);
b.Elements.Add(new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8));
b.Elements.Add(new HttpsTransportBindingElement());

WSClient svc = new WSClient(b, new EndpointAddress(new Uri("https://serviceurl.com/SoapWS"), new DnsEndpointIdentity("CertificateIdentity"), new AddressHeaderCollection()));
svc.ClientCredentials.UserName.UserName = "username";
svc.ClientCredentials.UserName.Password = "password";

svc.ClientCredentials.ClientCertificate.Certificate = new X509Certificate2("Certificate.p12", "password");
svc.ClientCredentials.ServiceCertificate.DefaultCertificate = new X509Certificate2("Certificate.p12", "password");
svc.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.None;

string resp = svc.DoSomething();

While this seems to be signing the message with the certificate (haven't been able to fully check), the basic authentication part is not happening. The response from the server is:

The HTTP request is unauthorized with client authentication scheme 'Anonymous'. The authentication header received from the server was 'Basic realm="realm"'.

Any insights on how I could get this binding to authenticate over transport with BASIC authentication would be very helpful. Thanks in advance.

PS: please note that I have no control over the web service I am trying to communicate with.

Foi útil?

Solução

Configure the https transport channel:

HttpsTransportBindingElement h = new HttpTransportBindingElement();
h.AuthenticationScheme = AuthenticationSchemes.Digest;
h.realm = ...

If you get into trouble I suggest to first set up a workign transport basic http binding just so you would see you pass throguh the server https transport (you should expect to get a soap fault b/c lack of signature).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top