Reputation: 31
We are working on a Windows 8 Store application which is accessing a WCF Service. For Security the SVC has a Credentials to be provided to access every method available out there. The Password type has been set as PasswordText. When i try to access the WCF i am getting an error as "An error occurred when verifying security for the message.” My Client side code is as follows:
CustomBinding binding = new CustomBinding();
binding.SendTimeout = TimeSpan.FromMinutes(2);
binding.OpenTimeout = TimeSpan.FromMinutes(2);
binding.CloseTimeout = TimeSpan.FromMinutes(2);
binding.ReceiveTimeout = TimeSpan.FromMinutes(10);
binding.Elements.Add(new TextMessageEncodingBindingElement( MessageVersion.Soap12WSAddressing10, System.Text.Encoding.UTF8));
binding.Elements.Add(new HttpTransportBindingElement());
binding.Name = "ClearUsernameBinding_IUserDetailsService";
EndpointAddress endpoint = new EndpointAddress(new Uri("http://MyURL"));
ServiceReference1.UserDetailsServiceClient proxy = new ServiceReference1.UserDetailsServiceClient(binding, endpoint);
proxy.Endpoint.Contract.Name = "IScheduledVisitsService";
proxy.Endpoint.Contract.ConfigurationName = "ClearUsernameBinding_IScheduledVisitsService";
proxy.Endpoint.Address = endpoint;
proxy.Endpoint.Binding = binding;
proxy.ClientCredentials.UserName.UserName = Loginmodel.UserName;
proxy.ClientCredentials.UserName.Password = Loginmodel.Password;
UserDTO result = await proxy.GetUserByUsernameAsync(Loginmodel.UserName);
It seems the password has to be set a PasswordText, Any idea how to get this resolved
Upvotes: 0
Views: 759
Reputation: 1541
Here's what I did to get it to work:
CustomBinding binding = new CustomBinding();
binding.Name = "ClearUsernameBinding_IUserDetailsService";
binding.SendTimeout = TimeSpan.FromMinutes(2);
binding.OpenTimeout = TimeSpan.FromMinutes(2);
binding.CloseTimeout = TimeSpan.FromMinutes(2);
binding.ReceiveTimeout = TimeSpan.FromMinutes(10);
binding.Elements.Add(new TextMessageEncodingBindingElement(MessageVersion.Soap11, System.Text.Encoding.UTF8));
binding.Elements.Add(TransportSecurityBindingElement.CreateUserNameOverTransportBindingElement());
binding.Elements.Add(new HttpsTransportBindingElement());
EndpointAddress endpoint = new EndpointAddress(new Uri("https://MYURL"));
ServiceReference1.UserDetailsServiceClient proxy = new ServiceReference1.UserDetailsServiceClient(binding, endpoint);
proxy.Endpoint.Contract.Name = "IScheduledVisitsService";
proxy.Endpoint.Contract.ConfigurationName = "ClearUsernameBinding_IScheduledVisitsService";
proxy.Endpoint.Address = endpoint;
proxy.Endpoint.Binding = binding;
proxy.ClientCredentials.UserName.UserName = Loginmodel.UserName;
proxy.ClientCredentials.UserName.Password = Loginmodel.Password;
UserDTO result = await proxy.GetUserByUsernameAsync(Loginmodel.UserName);
Which is the equivalent of the following if done in config
<binding name="myBinding">
<security defaultAlgorithmSuite="Default" authenticationMode="UserNameOverTransport"
requireDerivedKeys="true"
includeTimestamp="true"
messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10">
</security>
<textMessageEncoding messageVersion="Soap11" />
</binding>`
But like SuMMeR said, this will only work with HTTPS. If you want to allow for insecure, you can add the allowInsecureTransport="true"
to the <security>
element in the config file. If you want to do it in code, I think you could just try something like:
TransportSecurityBindingElement mySecElement = new TransportSecurityBindingElement { AllowInsecureTransport = true };
binding.Elements.Add(mySecElement);
Upvotes: 1
Reputation: 97
By default it is not allowed to send client credentials in an unsecure way in WCF. So look at the following senarious how to protect your service:
Also there is a workarownd that allows to send client credentials unencrypted over HTTP: SecurityBindingElement.AllowInsecureTransport. But you shouldn't use it in production because it opens a serious security flaw.
Upvotes: 0