I've been trying to get WCF security working for my project, and have had little luck. I'm trying to create a service that uses net.tcp as the binding, and does both message and transport security. Message security is done using username and password and transport security is done (supposedly!) using certificates.
For my development testing, I created my own certificate authority and placed this certificate in my computer's trusted store (LocalMachine). I then created two certificates, each signed by my certificate authority, one for the service to use, and one for the client app to use. I placed both of these in the Personal store (My) in LocalMachine. Then, for testing I created a random certificate that wasn't signed by my certificate authority (and therefore is untrusted) and placed that in the Personal store in LocalMachine. I used makecert to create these certificates.
I then configured the client app that connects to the service to use the invalid untrusted certificate as its client certificate. The service is set (supposedly) to check the client certificates using chain trust. However, this client is able to connect and successfully talk to the service! It should be being rejected, because its certificate is untrusted!
I don't know what's causing this behaviour, so I submit the issue to you guys to see what you make of it. Here are my WCF configurations:
Service conf:
<system.serviceModel>
<services>
<service behaviorConfiguration="DHTestBehaviour" name="DigitallyCreated.DHTest.Business.DHTestBusinessService">
<endpoint address="" binding="netTcpBinding" contract="DigitallyCreated.DHTest.Business.IDHTestBusinessService" bindingConfiguration="DHTestNetTcpBinding" bindingNamespace="http://www.digitallycreated.net/DHTest/v1" />
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:8090/"/>
<add baseAddress="http://localhost:8091/"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="DHTestBehaviour">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="MembershipProvider" membershipProviderName="DHTestMembershipProvider"/>
<serviceCertificate storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectDistinguishedName" findValue="CN=business.dhtestDHTest.com" />
<clientCertificate>
<authentication certificateValidationMode="ChainTrust" trustedStoreLocation="LocalMachine" revocationMode="NoCheck" />
</clientCertificate>
</serviceCredentials>
<serviceAuthorization principalPermissionMode="UseAspNetRoles" roleProviderName="DHTestRoleProvider" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<netTcpBinding>
<binding name="DHTestNetTcpBinding">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName"/>
<transport clientCredentialType="Certificate" protectionLevel="EncryptAndSign"/>
</security>
</binding>
</netTcpBinding>
</bindings>
</system.serviceModel>
Client Conf:
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="NetTcpBinding_IDHTestBusinessService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions"
hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxBufferPoolSize="524288"
maxBufferSize="65536" maxConnections="10" maxReceivedMessageSize="65536">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Certificate" protectionLevel="EncryptAndSign" />
<message clientCredentialType="UserName" />
</security>
</binding>
</netTcpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="DHTestBusinessServiceEndpointConf">
<clientCredentials>
<clientCertificate storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectDistinguishedName" findValue="CN=invalid"/>
<serviceCertificate>
<authentication revocationMode="NoCheck" trustedStoreLocation="LocalMachine"/>
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<client>
<endpoint address="net.tcp://phoenix-iv:8090/" binding="netTcpBinding"
behaviorConfiguration="DHTestBusinessServiceEndpointConf"
bindingConfiguration="NetTcpBinding_IDHTestBusinessService"
contract="DHTest.NetTcp.Business.IDHTestBusinessService"
name="NetTcpBinding_IDHTestBusinessService">
<identity>
<dns value="business.dhtest.com" />
</identity>
</endpoint>
</client>
</system.serviceModel>
The client username/password auth code:
DHTestBusinessServiceClient client = new DHTestBusinessServiceClient();
client.ClientCredentials.UserName.UserName = "ratfink";
client.ClientCredentials.UserName.Password = "testpassword";
Thank you for your help in advance.
EDIT (2009/06/01):
One of my friends pointed me towards a blog that answers the question as to why this is occurring. Apparently, when you specify TransportWithMessageCredential is means exactly that: Transport with Message Credentials only. This is why my certificates are being ignored on the transport level.
However, I don't consider the issue complete and closed, because I still want to do this. :) I'm going to look into custom certificate validators that I think I can plug in and see if that works. I'll get back to you all with the results.
EDIT (2009/06/08):
No, custom certificate validators don't work either. WCF simply doesn't call them.
I found a solution to my problem, however, it turned out to be a lot nastier than I expected.
Basically, to achieve both Transport and Message credential checking you need to define a custom binding. (I found info to this effect here).
I found the easiest way to do this is to continue doing your configuration in the XML, but at runtime copy and slightly modify the netTcp binding from the XML configuration. There is literally one switch you need to enable. Here's the code on the service side and on the client side:
Service Side
ServiceHost businessHost = new ServiceHost(typeof(DHTestBusinessService));
ServiceEndpoint endpoint = businessHost.Description.Endpoints[0];
BindingElementCollection bindingElements = endpoint.Binding.CreateBindingElements();
SslStreamSecurityBindingElement sslElement = bindingElements.Find<SslStreamSecurityBindingElement>();
sslElement.RequireClientCertificate = true; //Turn on client certificate validation
CustomBinding newBinding = new CustomBinding(bindingElements);
NetTcpBinding oldBinding = (NetTcpBinding)endpoint.Binding;
newBinding.Namespace = oldBinding.Namespace;
endpoint.Binding = newBinding;
Client Side
DHTestBusinessServiceClient client = new DHTestBusinessServiceClient();
ServiceEndpoint endpoint = client.Endpoint;
BindingElementCollection bindingElements = endpoint.Binding.CreateBindingElements();
SslStreamSecurityBindingElement sslElement = bindingElements.Find<SslStreamSecurityBindingElement>();
sslElement.RequireClientCertificate = true; //Turn on client certificate validation
CustomBinding newBinding = new CustomBinding(bindingElements);
NetTcpBinding oldBinding = (NetTcpBinding)endpoint.Binding;
newBinding.Namespace = oldBinding.Namespace;
endpoint.Binding = newBinding;
You'd think that'd be it, but you'd be wrong! :) This is where it gets extra lame. I was attributing my concrete service methods with PrincipalPermission to restrict access based on roles of the service user like this:
[PrincipalPermission(SecurityAction.Demand, Role = "StandardUser")]
This started failing as soon as I applied the above changes. The reason was because the
OperationContext.Current.ServiceSecurityContext.PrimaryIdentity
was ending up being an unknown, username-less, unauthenticated IIdentity. This was because there are actually two identities representing the user: one for the X509 certificate used to authenticate over Transport, and one for the username and password credentials used to authenticate at Message level. When I reverse engineered the WCF binaries to see why it wasn't giving me my PrimaryIdentity I found that it has an explicit line of code that causes it to return that empty IIdentity if it finds more than one IIdentity. I guess it's because it's got no way to figure out which one is the primary one.
This means using the PrincipalPermission attribute is out the window. Instead, I wrote a method to mimic its functionality that can deal with multiple IIdentities:
private void AssertPermissions(IEnumerable<string> rolesDemanded)
{
IList<IIdentity> identities = OperationContext.Current.ServiceSecurityContext.AuthorizationContext.Properties["Identities"] as IList<IIdentity>;
if (identities == null)
throw new SecurityException("Unauthenticated access. No identities provided.");
foreach (IIdentity identity in identities)
{
if (identity.IsAuthenticated == false)
throw new SecurityException("Unauthenticated identity: " + identity.Name);
}
IIdentity usernameIdentity = identities.Where(id => id.GetType().Equals(typeof(GenericIdentity))).SingleOrDefault();
string[] userRoles = Roles.GetRolesForUser(usernameIdentity.Name);
foreach (string demandedRole in rolesDemanded)
{
if (userRoles.Contains(demandedRole) == false)
throw new SecurityException("Access denied: authorisation failure.");
}
}
It's not pretty (especially the way I detect the username/password credential IIdentity), but it works! Now, at the top of my service methods I need to call it like this:
AssertPermissions(new [] {"StandardUser"});
check out the Codeplex - Intranet Section that provides checklists for different scenarios. The other thing to mention is that netTcpBindings are not supported for use within IIS5.0 and IIS6.0 - see 3rd paragraph here, only IIS7.0+.
Related
I have a Net Framework 4.5 WCF Service, running with async/task methods. It is deployed on a valid URL, with a correct Digicert certificate, assuring the domain. We have a "client certificate", with a "one-to-one" mapping, and all its ok for our "Winforms" apps.
Now, we wan't to call it from our Android/iOS Xamarin projects.
We know that Xamarin doesn't supports wsBinding, so we're are using this config:
Server
<system.serviceModel>
<services>
<service
name="serviceWCF.nameService"
behaviorConfiguration="behavior_base">
<endpoint address=""
binding="basicHttpBinding"
bindingConfiguration="transport"
contract="serviceWCF.nameInterfaceService" />
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="transport">
<security mode="Transport" >
<transport clientCredentialType="Certificate"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="behavior_base">
<serviceMetadata httpsGetEnabled="true" httpsGetUrl=""/>
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
</system.serviceModel>
We created a proxy from SVCUTIL.EXE, then we have implement manually the async methods, channel creation, because Xamarin doesn't supports dinamic bindings, and so on.
The proxy for our Xamarin client app, it's invoked so:
BasicHttpBinding binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
AddressHeader addressHeader2;
AddressHeader[] addressHeaders;
EndpointAddress endpoint;
addressHeader2 = AddressHeader.CreateAddressHeader("nameapp_iOS", "https:\\URL_WCF_Service.svc", 0);
addressHeaders = new AddressHeader[]{ addressHeader2};
endpoint = new EndpointAddress(new System.Uri("https:\\URL_WCF_Service.svc"),addressHeaders);
System.Security.Cryptography.X509Certificates.X509Certificate2 oCert;
oCert = new System.Security.Cryptography.X509Certificates.X509Certificate2(System.IO.File.ReadAllBytes("CertBundle.pfx"), "pass");
Service_MovilClient oProxy = new Service_MovilClient(binding, endpoint);
Service_MovilClient oProxy.ClientCredentials.ClientCertificate.Certificate = oCert
But ... nothing happens... time out....
The server it's ok. The url can be accessed from the iOS emulator. We can use it with only "basicHttpBinding", but, we want to use SSL+Client Certificate.
Any ideas? Now I'm stuck.
It's worthless to spoil more efforts. By now, WCF Xamarin its very short.
I have to settle for with HTTPs and a basic Transport Security (security mode="Transport").
I have to use that Wcf services ... But if you, pathetic human, are reading this prior a new development, use REST services. They have a much better support form Xamarin.
My project used visual studio 2010 and is a web application project with c#. I add web referrence for the web service.
I'm having could not establish secure channel for SSL/TLS with authority when i try to access third party web service with certificate in my UAT server. The certificate was expired. I've already add the trust root cert and personal cert for local computer and current user. It works when i call with web service application but not with web application
Below code I used to add the certificate when calling web service and bypass the certificate error.
AServiceReference.AServiceClient client = new AServiceReference.AServiceClient();
X509Certificate2 cert = new X509Certificate2("CERTIFICATE","PASSWORD");
client.ClientCredentials.ClientCertificate.Certificate = cert;
System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
Add this in your web.config file and you will be fine probably:
<bindings>
<basicHttpBinding>
<binding name="xxxBinding">
<security mode="Transport">
<transport clientCredentialType="Certificate"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
When I was tasked with attaching a client cert I was able to do it in one of two ways. It doesn't look like you're actually attaching the client cert (if you are using one) anywhere.
1: through code like you've been doing
proxyClient.ClientCredentials.ClientCertificate.SetCertificate(
StoreLocation.CurrentUser,
StoreName.My,
X509FindType.FindByThumbprint,
"6D0DBF387484B25A16D0E3E53DBB178A366DA954");
2: through configuration in the web/app.config file.
<behaviors>
<endpointBehaviors>
<behavior name="ohBehave">
<clientCredentials useIdentityConfiguration="false">
<clientCertificate findValue="c6dafea24197cd6a6f13e846ffcdf70220d23ec2" storeLocation="CurrentUser"
x509FindType="FindByThumbprint" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<client>
<endpoint address="https://myservice.ca/SubmitService/Submit.svc"
behaviorConfiguration="ohBehave" binding="customBinding" bindingConfiguration="SubmitBinding"
contract="SubmitService.Submit" name="SubmitDev" />
</client>
As long as the cert is in the store specified it should be getting attached.
I also had to use a customBinding in my .config file since we wanted to pass credentials as well (note the httpsTransport node for client certs):
<binding name="SubmitBinding">
<security defaultAlgorithmSuite="Default" authenticationMode="UserNameOverTransport"
requireDerivedKeys="true" includeTimestamp="true" messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10">
<localClientSettings detectReplays="false" />
<localServiceSettings detectReplays="false" />
</security>
<textMessageEncoding messageVersion="Soap11">
<readerQuotas maxDepth="32" maxStringContentLength="200000000"
maxArrayLength="200000000" maxBytesPerRead="200000000" />
</textMessageEncoding>
<httpsTransport maxBufferPoolSize="200000000" maxReceivedMessageSize="200000000"
maxBufferSize="200000000" requireClientCertificate="true" />
</binding>
I have a question around WCF authorization against a domain account over HTTP traffic hosted on IIS (none production so no ssl cert was available to use over the internet)
I'd like to know how to set up windows authentication from a client to my web service. currently I'm testing on the same LAN so proxies are not a problem
I have included a list of tried steps at the end of this post
Edit: The error that is occurring is just Access is denied, nothing else, given from the
try, catch in the Client Application. If there is a way to get more detailed information, please let me know and ill add the result to the post.
WCF Service code:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single, IncludeExceptionDetailInFaults = true)]
public class Data : IData
{
[PrincipalPermission(SecurityAction.Demand, Role=#"Administrators")]
public List<Incident> GetCases()
{
Queries query = new Queries();
List<Incident> iList = query.CallCases();
return iList;
}
}
WCF Web Config Bindings:
<wsHttpBinding>
<binding name="TransportSecurity">
<security mode="None">
<message clientCredentialType="Windows" algorithmSuite="Default"/>
</security>
</binding>
</wsHttpBinding>
WCF Web Config Behavior:
<behavior name="Behaviour1">
<serviceMetadata httpGetEnabled="true" httpGetUrl=""/>
<serviceDebug includeExceptionDetailInFaults="true" />
<useRequestHeadersForMetadataAddress>
<defaultPorts>
<add scheme="http" port="9577" /> ///This port is correct
</defaultPorts>
</useRequestHeadersForMetadataAddress>
</behavior>
WCF Web Config Service:
<service behaviorConfiguration="Behaviour1" name="WebService1.Data">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="TransportSecurity" contract="WebService1.IData">
<identity>
<dns value="demo.DomainName.co.uk" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
Client Application (Has Service reference added)
DataClient client = new DataClient();
AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
PrincipalPermission principalPerm = new PrincipalPermission(null, "Administrators");
principalPerm.Demand();
Console.WriteLine("Demand succeeded.");
client.ClientCredentials.Windows.ClientCredential.Domain = "Domain Name";
client.ClientCredentials.Windows.ClientCredential.UserName = "User Account";
client.ClientCredentials.Windows.ClientCredential.Password = "Password";
//client.ClientCredentials.UserName.UserName = #"UserAccount#domain.com";
//client.ClientCredentials.UserName.Password = "Password";
//client.ClientCredentials.UseIdentityConfiguration = true;
try
{
List<Incident> cases = client.GetCases().ToList();
foreach (Incident Inc in cases)
{
Console.WriteLine(Inc.CaseID);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Attempted Resolutions:
Using Domain and Local Users
Modifying the Client Credential type to basic, NTLM and Windows
using setting IIS to use
IIS has Basic and Windows Authentication Enabled
if you need any more information please don't hesitate to ask.
Thanks for any help you can provide
#Tim pointed me in the right direction, this was the resolution:
<wsHttpBinding>
<binding name="TransportSecurity">
<security mode="Message">
<message clientCredentialType="Windows" algorithmSuite="Default"/>
</security>
</binding>
</wsHttpBinding>
Because I have no SSL Certificate I needed to set the security mode to Message, I was getting confused as most people test using SSL, which would require transport security as well I had set it to None for testing.
Thanks for the help Tim
I have a WCF application hosted on IIS 6 that needs to
Have 2-way SSL authentication
Validate client certificate content with some client host information
Validate client certificate is issued by the valid subCA.
I was able to do 1) successfully. I am trying to achieve 2) and 3) by following this - basically creating a class that inherits X509CertificateValidator and overriding the Validate method with my own validation implementation(step 2 and 3). I followed the MSDN instructions exactly however, it seem that the Validate method is not being called. I purposely throw a SecurityAccessDeniedException in the overidden Validate method and no exception is thrown when I tried to access the service via my browser. I can still access my website with any client certificate.
I also read this thread but it didn't really help. Any help would be greatly appreciated!
Here's my configuration:
<system.serviceModel>
<services>
<service behaviorConfiguration="SimpleServiceBehavior"
name="SampleNameSpace.SampleClass">
<endpoint address=""
binding="basicHttpBinding"
bindingConfiguration="NewBinding0"
contract="SampleNameSpace.ISampleClass" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="SimpleServiceBehavior">
<serviceMetadata httpsGetEnabled="true" policyVersion="Default" />
<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="Custom" customCertificateValidatorType="SampleNameSpace.MyX509CertificateValidator, SampleAssembly"/>
</clientCertificate>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="NewBinding0">
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding>
</basicHttpBinding>
</bindings>
You can also try to override certificate validation with this ServerCertificateValidationCallback
We are using it with WCF HttpBinding in such way:
System.Net.ServicePointManager.ServerCertificateValidationCallback =
(sender, certificate, chain, policyErrors) =>
{
var isValid = false;
// some checking logic
return isValid;
};
This a question that already has been discussed a couple of times on SO but I couldn't find any suitable solution to my problem. I have a WCF service hosted on an external server (other domain) and I'm trying to consume it from a command line application. I receive the following error:
The request for security token could not be satisfied because authentication failed.
The service is configured inside a web.config file:
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="wsHttpBinding_IRun">
<security mode="None">
<message clientCredentialType="None" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<serviceHostingEnvironment>
<baseAddressPrefixFilters>
<add prefix="http://www.domain.net"/>
</baseAddressPrefixFilters>
</serviceHostingEnvironment>
<behaviors>
<serviceBehaviors>
<behavior name="calculadora.SOA.RunBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="calculadora.SOA.RunBehavior" name="calculadora.SOA.Run">
<endpoint address="http://www.domain.net/calculadora/SOA/run.svc" binding="wsHttpBinding" contract="calculadora.SOA.IRun">
<identity>
<dns value="domain.net"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
</system.serviceModel>
On the client side, I create a custom binding to connect to the service. Here is the security configuration:
standardBinding.Security.Mode = SecurityMode.None;
standardBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
standardBinding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
standardBinding.Security.Transport.Realm = "";
standardBinding.Security.Message.ClientCredentialType = MessageCredentialType.None;
standardBinding.Security.Message.NegotiateServiceCredential = false;
standardBinding.Security.Message.EstablishSecurityContext = false;
standardBinding.Security.Message.AlgorithmSuite = SecurityAlgorithmSuite.Default;
I'm not using any security mechanism for authentification but still, the service seems to be expecting one. When working on different domains, is it mandatory to use a basic authentification?
EDIT: I wasn't referencing any binding configuration at my endpoint. Once the reference was set, I received another message error:
{"The message with Action 'http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue' 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)."}
The issue was caused by my client's binding. While I was creating my custom binding using the standard 'WSHttpBinding', the 'SecurityMode' property was set to 'Message' instead of 'None'. Now the code looks like the following and the service finally works:
WSHttpBinding standardBinding = new WSHttpBinding(SecurityMode.None, false);
CustomBinding myCustomBinding = new CustomBinding(standardBinding);
Many thanks to marc_s!
I think the problem is your service endpoint definition:
<endpoint address="http://www.domain.net/calculadora/SOA/run.svc"
binding="wsHttpBinding" contract="calculadora.SOA.IRun">
You are using the standard wsHttpBinding - which defaults to integrated Windows security as message security.
While you do define a binding configuration (called wsHttpBinding_IRun), you're not referencing it in your endpoint definition - thus it doesn't come into play. You need to extend your service endpoint definition with a bindingConfiguration attribute like so:
<endpoint address="http://www.domain.net/calculadora/SOA/run.svc"
binding="wsHttpBinding"
bindingConfiguration="wsHttpBinding_IRun"
contract="calculadora.SOA.IRun">
in order to actually use your defined binding configuration (including the security settings).
I ran into the same issue and after a whole day invested, finally I figure out how to fix. The key is put establishSecurityContext="false" into message tag.
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="UserName" establishSecurityContext="false" />
</security>