I have a WCF service, hosted in IIS 7.0 that needs to run database queries. In order to get the right permissions to do this I am impersonating within the service as follows:
[OperationBehavior(Impersonation = ImpersonationOption.Allowed)]
public void MyOperation(int arg)
<behavior name="ReceivingServiceBehavior">
<!-- Other behaviors -->
<serviceAuthorization impersonateCallerForAllOperations="true" />
</behavior>
When I try to connect and run my query I get the following:
Exception - System.IO.FileLoadException: Could not load file or assembly 'System.Transactions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' or one of its dependencies. Either a required impersonation level was not provided, or the provided impersonation level is invalid. (Exception from HRESULT: 0x80070542) File name: 'System.Transactions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' ---> System.Runtime.InteropServices.COMException (0x80070542): Either a required impersonation level was not provided, or the provided impersonation level is invalid. (Exception from HRESULT: 0x80070542) at System.Data.Linq.SqlClient.SqlConnectionManager.UseConnection(IConnectionUser user) at System.Data.Linq.SqlClient.SqlProvider.get_IsSqlCe() at System.Data.Linq.SqlClient.SqlProvider.InitializeProviderMode() at System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query) at System.Data.Linq.DataQuery`1.System.Collections.Generic.IEnumerable.GetEnumerator() at System.Linq.Buffer`1..ctor(IEnumerable`1 source) at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source) at Fourth.GHS.MessageRelay.RegistrationDBStorage.FindRegistration(SystemKey key)
Does your WCF client set the required "allowed impersonation level":
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<!-- .... -->
<behaviors>
<endpointBehaviors>
<behavior name="ImpersonationBehavior">
<clientCredentials>
<windows allowedImpersonationLevel="Impersonation" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
By default this is set to Identification if nothing is specified explicitly. Check out this blog post for more info.
If you want the SQL queries to be executed as the impersonated identity, you may actually need to enable delegation to your SQL server. Check out this article for more info:
thank you guys, I solved it by reading the XML under the declaration of:
[OperationBehavior(Impersonation:=ImpersonationOption.Required)]
it worked only when I read the XML directly from the WCFService Class.
Hmmm... I don't know. However, you could force the dll to load early on. Since you are using IIS, this would presumably be in your global.asax - something like creating and throwing away a TransactionScope should do the job...
Having played around with this some more, the easiest solution for IIS hosted services is to run your Application Pool with the identity of a domain user that has the requisite permissions. There are probably issues with this in terms of security but for our purposes it's good enough. We can restrict the permissions given to that user but everything works without having to get into Kerberos, impersonation, delegation and the mysteries of AD.
Thank you huseyint. I've been fighting this one for the past day and a half. Here's some stuff that would have saved me a ton of time. So hopefully it will save someone else some time. I was having problems with the SQLConnection and impersonation throwing a registry access is denied using transport security. I tried even using transportwithmessagecredential. Inside of procmon I was getting "Bad Impersonation". My config is IIS 7, virtual dir only has windows authentication enabled and I disabled kernel mode authentication. Basic settings I set it to use pass through authentication.
Service Config -
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="false" />
<services>
<service behaviorConfiguration="SymitarService.ScheduleServiceBehavior" name="SymitarService.ScheduleService">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="wsSecure" contract="SymitarService.IScheduleService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="wsHttpBinding" bindingConfiguration="wsSecure" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="SymitarService.UserDirectoryBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceAuthorization impersonateCallerForAllOperations="true" />
</behavior>
<behavior name="SymitarService.ScheduleServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceAuthorization impersonateCallerForAllOperations="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<netTcpBinding>
<binding name="tcpSecure" portSharingEnabled="true" />
</netTcpBinding>
<wsHttpBinding>
<binding name="wsSecure" allowCookies="true">
<security mode="Transport">
<transport clientCredentialType="Windows" proxyCredentialType="Windows" />
<message clientCredentialType="Windows" negotiateServiceCredential="true" />
</security>
</binding>
</wsHttpBinding>
<mexTcpBinding>
<binding name="mexSecure" />
</mexTcpBinding>
</bindings>
</system.serviceModel>
and the client
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IScheduleService" closeTimeout="01:00:00" openTimeout="01:00:00" receiveTimeout="01:00:00" sendTimeout="01:00:00" bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" useDefaultWebProxy="true" allowCookies="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:20:00" enabled="false" />
<security mode="Transport">
<transport clientCredentialType="Windows" proxyCredentialType="Windows" realm="" />
<message clientCredentialType="Windows" negotiateServiceCredential="true" establishSecurityContext="true" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="ImpersonationBehavior">
<clientCredentials>
<windows allowedImpersonationLevel="Impersonation" allowNtlm="true"/>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<client>
<endpoint address="https://server:444/SymitarService/ScheduleService.svc"
binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_IScheduleService"
contract="Symitar.ScheduleService.IScheduleService"
name="WSHttpBinding_IScheduleService"
behaviorConfiguration="ImpersonationBehavior"
>
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</client>
</system.serviceModel>
This one solved my problem.
Right click on Visual studio (whichever version you use) Properties Select compatibility tab Fill the checkbox which says "Run this program as administrator" Open the project from the file location Run the application
User contributions licensed under CC BY-SA 3.0