InvalidSecurity when I try to soap call my WCF with Username and Password
soap, wcf
Solution
I struggled with this same issue for several weeks and finally got PHP clients to authenticate with my WCF service. This configuration is what I currently have working in production.
First off, you have to enable Anonymous auth AND Basic auth. You have to leave Anonymous turned on so the client can read the WSDL before they authenticate. Even though anonymouse auth is enabled they will not be able to use your service without being authenticated first.
Put this in your web.config or turn on Anonymous AND Basic Authentication in IIS directly:
<security>
<authentication>
<anonymousAuthentication enabled="true" />
<basicAuthentication enabled="true" />
</authentication>
</security>
Then setup your WCF security to use Basic auth and Transport security:
<bindings>
<basicHttpBinding>
<binding name="SSLBinding">
<security mode="Transport">
<transport clientCredentialType="Basic" />
</security>
</binding>
</basicHttpBinding>
</bindings>
And here is my behavior:
<behaviors>
<serviceBehaviors>
<behavior name="SSLBehavior">
<serviceMetadata httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceSecurityAudit auditLogLocation="Application"
serviceAuthorizationAuditLevel="Failure"
messageAuthenticationAuditLevel="Failure"
suppressAuditFailure="true" />
</behavior>
</serviceBehaviors>
</behaviors>
Use this to decorate your methods to control who can access what:
[PrincipalPermission(SecurityAction.Demand, Role = @"DOMAIN\ActiveDirectoryGroup")]
Using this setup the PHP client should be able to get the WSDL then call your method after authorization:
$url = 'https://domain.com/service.svc?wsdl';
$username = 'username';
$password = 'password';
$options = array(
'login' => $username,
'password' => $password,
'soap_version' => SOAP_1_1,
'exceptions' => true,
'trace' => 1,
'cache_wsdl' => WSDL_CACHE_NONE,
'compression' => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP,
'connection_timeout' => 60
);
$client = new SoapClient($url, $options);
$obj = new YourObject();
$obj->MyProperty = 'Test';
$obj->MyOtherProperty = 'Testing';
$result = $client->WCFMethodName(array('paramName' => $obj));
It's VERY important that the parameter name in your PHP code match the WCF parameter name EXACTLY (case sensitive).
Problem
Error `[a:InvalidSecurity] An error occurred when verifying security for the message.` I try to call my service like this. php ``` <?php $soapURL = "https://localhost:8888/wcf/?wsdl" ; $soapParameters = Array('userName' => "user23", 'password' => "pass123") ; $soapClient = new SoapClient($soapURL, $soapParameters); var_dump($soapClient->GetVersion()); ?> ``` I got it to work before with no authentication so the fault lies here in the php code or in my app.config on the WCF i believe. here is my app.config ``` <?xml version="1.0"?> <configuration> <system.serviceModel> <services> <service behaviorConfiguration="MYDLL.Behavior" name="MYDLL.WCFService"> <endpoint address="" binding="basicHttpBinding" bindingConfiguration="UsernameAndSSL" name="basicHttpBinding" contract="MYDLL.IService"/> <endpoint address="mex" binding="mexHttpsBinding" bindingConfiguration="" name="MexBinding" contract="IMetadataExchange"/> <host> <baseAddresses> <add baseAddress="https://localhost:8734/wcf/"/> </baseAddresses> </host> </service> </services> <behaviors> <serviceBehaviors> <behavior name="MYDLL.Behavior"> <serviceMetadata httpsGetEnabled="true"/> <serviceCredentials> <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="MYDLL.CustomUserNameValidator, MYDLL"/> <serviceCertificate findValue="localhost" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName"/> </serviceCredentials> <useRequestHeadersForMetadataAddress /> </behavior> </serviceBehaviors> </behaviors> <bindings> <basicHttpBinding> <binding name="UsernameAndSSL"> <security mode="TransportWithMessageCredential"> <transport clientCredentialType="Basic"/> <message clientCredentialType="UserName"/> </security> </binding> </basicHttpBinding> </bindings> </system.serviceModel> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0,Profile=Client"/> </startup> </configuration> ``` and the customusernamevalidator ``` public class CustomUserNameValidator : UserNamePasswordValidator { public override void Validate(string userName, string password) { Console.WriteLine("User validation succeeded (Username: {0}; Password: {1})", userName, password); } } ``` What I dont get is if the fault are in my php code or in the config. the consolewrite does not run, and I just get that invalidSecurity exception so it seems it knows I have an customusernamevalidation that it cant find?