Username and certificate both on transport level
Not an answer to this question, but the question title brought me here, so maybe others also:
I needed a Soap11-binding with both certificate (for the gateway) and username on transport level (for the application). (Both parts were maintained by different teams and different suppliers at the customer site.)
Despite the name a customBinding
with UserNameOverTransport
sends the username&password in the Soap-header (message-level), not in the http-header (transport-level), leading to this inner FaultException
in SecurityRequestChannel.ProcessReply
, originating from the application:
FaultException: MustUnderstand headers: [{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}Security] are not understood.
And using basicHttpBinding
with <security mode="TransportCredentialOnly">
leads to:
The provided URI scheme 'https' is invalid; expected 'http'.
Parameter name: via
After a lot of trial and error, it turned out this can be done by combining configuration and code.
Example of certificate over transport by configuration
<basicHttpBinding>
<binding name="myBasicHttpBindingForTransportCertificate">
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding>
</basicHttpBinding>
<endpointBehaviors>
<behavior name="myCertificateBehavior">
<clientCredentials>
<clientCertificate findValue="my certificate subject" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="My" />
</clientCredentials>
</behavior>
(I dynamically loaded it, using this answer.)
Example of username&password over transport by code
using (new OperationContextScope(client.InnerChannel))
{
…
var httpRequestProperty = new HttpRequestMessageProperty();
httpRequestProperty.Headers[System.Net.HttpRequestHeader.Authorization] =
"Basic " + Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes($"{username}:{password}"));
OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty;
(Thanks to this old answer to "WCF TransportCredentialOnly not sending username and password".)