Why, when I impersonate within a WCF service, can my service not load System.Transactions when I try to run a LINQ to SQL query?

8

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:

Code

[OperationBehavior(Impersonation = ImpersonationOption.Allowed)]
public void MyOperation(int arg)

Configuration

<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)
.net
sql-server
wcf
security
transactions
asked on Stack Overflow Nov 10, 2008 by Simon

7 Answers

6

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.

answered on Stack Overflow Nov 26, 2008 by huseyint
3

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:

http://msdn.microsoft.com/en-us/library/ms730088.aspx

answered on Stack Overflow Nov 10, 2008 by Kwal
1

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.

answered on Stack Overflow Jan 8, 2009 by (unknown user) • edited Aug 5, 2011 by PaĆ­lo Ebermann
0

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...

answered on Stack Overflow Nov 10, 2008 by Marc Gravell
0

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.

answered on Stack Overflow Nov 11, 2008 by Simon
0

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>
answered on Stack Overflow Jul 1, 2009 by (unknown user)
0

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

answered on Stack Overflow Mar 30, 2015 by Abdelrahman ELGAMAL

User contributions licensed under CC BY-SA 3.0