Trying to run WCF web service on non-domain VM, Security Errors
- by NealWalters
Am I in a Catch-22 situation here? My goal is to take a WCF service that I inherited, and run it on a VM and test it by calling it from my desktop PC. The VM is in a workgroup, and not in the company's domain. Basically, we need more test environments, ideally one per developer (we may have 2 to 4 people that need this). Thus the idea of the VM was that each developer could have his own web server that somewhat matches or real environment (where we actually have two websites, an external/exposed and internal).
[Using VS2010 .NET 4.0]
In the internal service, each method was decorated with this attribute:
[OperationBehavior(Impersonation = ImpersonationOption.Required)]
I'm still researching why this was needed. I think it's because a webapp calls the "internal" service, and either a) we need the credentials of the user, or b) we may doing some PrinciplePermission.Demands to see if the user is in a group. My interest is creating some ConsoleTest programs or UnitTest programs.
I changed to allowed like this:
[OperationBehavior(Impersonation = ImpersonationOption.Allowed)]
because I was getting this error in trying to view the .svc in the browser:
The contract operation 'EditAccountFamily' requires Windows identity for automatic impersonation. A Windows identity that represents the caller is not provided by binding ('WSHttpBinding','http://tempuri.org/') for contract ('IAdminService','http://tempuri.org/'.
I don't get that error with the original bindings look like this:
However, I believe I need to turn off this security since the web service is not on the domain.
I tend to get these errors in the client:
1) The request for security token could not be satisfied because authentication failed - as an InnerException of "SecurityNegotiation was unhandled".
or
2) The caller was not authenticated by the service as an InnerException of "SecurityNegotiation was unhandled".
So can I create some configuration of code and web.config that will allow each developer to work on his own VM? Or must I join the VM to the domain?
The number of permutations seems near endless. I've started to create a Word.doc that says what to do with each error, but now I'm in the catch-22 where I'm stuck.
Thanks,
Neal
Server Bindings:
<bindings>
<wsHttpBinding>
<binding
name="wsHttpEndpointBinding"
maxBufferPoolSize="2147483647"
maxReceivedMessageSize="500000000">
<readerQuotas
maxDepth="2147483647"
maxStringContentLength="2147483647"
maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647" />
<!-- <security mode="None" /> This is one thing I tried -->
<security>
<message
clientCredentialType="Windows" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior
name="ABC.AdminService.AdminServiceBehavior">
<!-- To avoid disclosing metadata information, set the value below to false and
remove the metadata endpoint above before deployment -->
<serviceMetadata
httpGetEnabled="true" />
<!-- To receive exception details in faults for debugging purposes, set the value below to true.
Set to false before deployment to avoid disclosing exception information -->
<serviceDebug
includeExceptionDetailInFaults="true" />
<serviceCredentials>
</serviceCredentials>
<!--<serviceAuthorization principalPermissionMode="UseAspNetRoles"
roleProviderName="AspNetWindowsTokenRoleProvider"/>-->
<serviceAuthorization
principalPermissionMode="UseWindowsGroups"
impersonateCallerForAllOperations="true" />
</behavior>
<behavior
name="ABC.AdminService.IAdminServiceTransportBehavior">
<!-- To avoid disclosing metadata information, set the value below to false and
remove the metadata endpoint above before deployment -->
<serviceMetadata
httpGetEnabled="true" />
<!-- To receive exception details in faults for debugging purposes, set the value below to true.
Set to false before deployment to avoid disclosing exception information -->
<serviceDebug
includeExceptionDetailInFaults="false" />
<serviceCredentials>
<clientCertificate>
<authentication
certificateValidationMode="PeerTrust" />
</clientCertificate>
<serviceCertificate
findValue="WCfServer"
storeLocation="LocalMachine"
storeName="My"
x509FindType="FindBySubjectName" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment
multipleSiteBindingsEnabled="true" />
CLIENT:
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IAdminService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="Message">
<transport clientCredentialType="Windows" proxyCredentialType="None"
realm="" />
<message clientCredentialType="Windows" negotiateServiceCredential="true"
algorithmSuite="Default" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://192.168.159.132/EC_AdminService/AdminService.svc"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IAdminService"
contract="svcRef.IAdminService" name="WSHttpBinding_IAdminService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</client>
</system.serviceModel>