Monday, May 13, 2013

Configuring Impersonation in WCF

First of all, there must be a very strong reason to use impersonation.  General consensus these days, is to avoid it.  This is generally because the further down the stack you travel away from the UI the more meaningless the user's credentials become.  Prefer instead to use a "Trusted Subsystem" approach where once the user is authenticated and authorised the subsystems downstream "trust" the upstream systems.

Valid reasons could be integrating with legacy systems or infrastructure requirements.

On the client:

  • Use a binding and security mode that supports passing credentials.
  • The client app must agree to allow the service impersonating its credentials.

                <behavior name="MyEndpointBehaviour">
                        <windows allowedImpersonationLevel="Impersonation"/>

On the service:

  • Decorate the service contract implementation with a operation behaviour that allows impersonation.
     [OperationBehavior(Impersonation = ImpersonationOption.Allowed)]
    Possible values are NotAllowed, Allowed or Required. In this case I used Allowed, because Impersonation is one option that could be used when deployed.  (The other option is running the App-Pool with credentials that can access downstream systems, for example SQL).
  • The service app.config must enable impersonation also.
                        <serviceAuthorization impersonateCallerForAllOperations="true" />
I found it useful when impersonation is required, to use the Allowed option on the service implementation.  This means that the remainder of the work is config, so you can change it after its deployed.

If you get any weird exceptions while testing, then the most common issue is not configuring the client to allow the service to impersonate it.  This is done with the endpointBehaviour snippet above.  In my case I was getting a service exception in the type initializer inside System.Data.SqlClient.SqlConnection and the inner exception is "requested registry access is not allowed"; enabling impersonation from the client side of the call fixed it.

No comments:

Post a Comment