0

I've consumed a WebReference and the receiving server requires a WS-Security header:

<wsse:UsernameToken wsu:Id="Example"> 
    <wsse:Username> ... </wsse:Username>
    <wsse:Password Type="..."> ... </wsse:Password>
    <wsse:Nonce EncodingType="..."> ... </wsse:Nonce>
    <wsu:Created> ... </wsu:Created>
</wsse:UsernameToken>

I'd assumed this would be included in the WSDL however after reading this post I understand that the logic should be separated.

The client class I use to perform the request contains a Proxy property IWebProxy:HttpWebClientProtocol. I believe this is where I should provide the header/override information. Please could someone confirm this?

I also have some code that I know generates the correct headers. However I'm unsure how to specify these headers/elements without modifying the WebReference.

public static Tuple<EndpointAddress, BindingElementCollection, string, string> PrepareGlowsAuth(string endpoint)
{
    EndpointAddress soapEndpoint = new EndpointAddress(string.Format("{0}/{1}", (IsProduction ? productionBaseUrl : testingBaseUrl), endpoint));
    BasicHttpsBinding binding = new BasicHttpsBinding();
    binding.Security.Mode = BasicHttpsSecurityMode.TransportWithMessageCredential;
    binding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;

    BindingElementCollection elements = binding.CreateBindingElements();
    elements.Find<SecurityBindingElement>().EnableUnsecuredResponse = true;

    return new Tuple<EndpointAddress, BindingElementCollection, string, string>(soapEndpoint, elements, "username", "password");
}

Would appreciate it if someone could point me in the right direction!

Update: After following advice I cant see the Client or Response classes.

Image to show the classes arent defined

atoms
  • 2,993
  • 2
  • 22
  • 43
  • Have you seen this s/o post? https://stackoverflow.com/questions/23663007/invoking-a-web-service-with-ws-security-from-net – tgolisch Jun 12 '19 at 18:47

1 Answers1

1

The way you would go about injecting the credentials into the request without altering the client class is as follows:

// Assume that you named your "Connected Service" com.example.foo

foo.bar requestObj= new foo.bar();

// Fill in your request object
bar.FirstName = "Someone";
// etc.

// Set up the authentication using the function you provided
var glowsAuthData = PrepareGlowsAuth("expressRateBook");

// foo.<object name>Client is automatically created, this is the generated
//   proxy class for communicating with the intended web service
foo.barClient client = new foo.barClient(new CustomBinding(glowsAuthData.Item2)
                                         , glowsAuthData.Item1);
client.ClientCredentials.UserName.UserName = glowsAuthData.Item3;
client.ClientCredentials.UserName.Password = glowsAuthData.Item4;

// Use the client to send the request object and populate the response object
// foo.<object name>Response is automatically generated when VS generates 
//   the code for "Connected Service". It also makes it the return type 
//   for foo.barClient.barResponse(foo.bar);
foo.barResponse responseObj = client.barResponse(requestObj);

Assuming no exceptions, responseObj will contain the response from the server. No direct modification to the generated client created using the WSDL required.

Tarek Fadel
  • 1,909
  • 1
  • 14
  • 22
  • Many thanks for this. Seems perfect. One issue though, I cant seem to find the WebServiceClass in System.Web.Services. Have ensured a ref to the dll v4 – atoms Jun 13 '19 at 13:28
  • So I have `WebService requestObj = new System.Web.Services.WebService();` But nothing for `WebServiceClassClient client = new WebServiceClassClient`. @Tarek, do I have to generate this class? – atoms Jun 13 '19 at 13:40
  • Unfortunate naming on my part, sorry. `requestObj`'s type should be the proxy class generated by VS when you import the WSDL. I named mine com.dhl.wsbexpress.expressRateBook. I was trying to keep it generic, but in doing so used a name used by the .NET framework. – Tarek Fadel Jun 13 '19 at 14:48
  • Thanks @Tarek. Unfortunately after following this I can't see the Client/Reponse classes that should have been generated. Maybe the WSDL or VS didnt correctly define the classes? (Runtime Version:4.0.30319.42000). Have added a image showing what I have. – atoms Jun 13 '19 at 15:32
  • Can also confirm the WSDL was generated from `https://wsbexpress.dhl.com/sndpt/expressRateBook?WSDL` – atoms Jun 13 '19 at 15:37
  • 1
    Ah, I think I see the issue. When you create the service reference, you need to go into advanced and select "Always Generate Message Contracts." I've created an example app which compiles and _should work_. You can download it from https://github.com/tHeCh0s3n0n3/.net-WSSE-example – Tarek Fadel Jun 13 '19 at 17:56
  • 1
    Many thanks Tarek! I was adding the wsdl as a web reference rather than a service reference. Very stupid mistake! – atoms Jun 13 '19 at 18:58