WCF Security – Impersonation
Hi, Gaurav Sharma here, I’m a developer with the Information Security Tools (IST) team. In today’s post I’ll concentrate on the topic of Impersonation in WCF.
Impersonation
- By definition, Impersonation is the act of assuming a different identity on a temporary basis so that a different security context or set of credentials can be used to access a resource
- There was no support for role based security in legacy technologies like C++. So, impersonation was adopted by developers to bridge this gap.
- When service uses Impersonation, it can assume identity of the client, primarily for the purpose of verifying clients authorization
- It is highly recommended to avoid impersonation for authorization and use Trusted Subsystem Pattern across implementation layers
Programmatic Impersonation
-
1: class SampleService : ISampleContract 2: { 3: public void MyMethod( ) 4: { 5: WindowsImpersonationContext impersonationContextObj = null; 6: impersonationContextObj = ServiceSecurityContext.Current.WindowsIdentity.Impersonate(); 7: try 8: { 9: // Operation performed here will be under client's identity 10: } 11: finally 12: { 13: impersonationContextObj.Undo(); 14: } 15: } 16: }
WindowsIdentity class provides a method Impersonate() which the service can call to impersonate client
Impersonate() returns an object of type WindowsImpersonationContext which contains a reference to service’s previous identity
Type WindowsImpersonationContext provides Undo() method which the service calls to revert it’s old identity.
Dispose() method also does the same. This allows us to write above code more elegantly with USING statement
-
Declaratively Impersonation
OperationBehavior attribute provides Impersonation property. Impersonation property refers to an enum of type ImpersonationOption
ImpersonationOption enumeration provides following options:
- Not Allowed – This is default value. WCF will not automatically impersonate but we can do it programmatically
- Allowed – Automatically impersonate caller if windows authentication is used and revert back once method returns
- Required – Throws exception when windows authentication is not used. All calls will be auto impersonated.
1: class SampleService : ISampleContract 2: { 3: [OperationBehavior(Impersonation = ImpersonationOption.Allowed)] 4: public void SampleServiceOperation( ) 5: { 6: // if windows authentication is used then 7: // operations performed here will ne under 8: // client's identity 9: } 10: }
Restricting Impersonation
- WCF allows clients to decide to what degree the service can get and use client’s identity
- WindowsClientCredential class provides AllowedImpersonationLevel enumeration which is defined as follows;
-
-
1: public enum TokenImpersonationLevel 2: { 3: None, 4: Anonymous, 5: Identification, 6: Impersonation, 7: Delegation 8: }
TokenImpersonationLevel
None – No client credentials are passed to service
Anonymous – No client credentials are passed. Anonymous and client are safest options for client’s but they provide no real usage. Only scenario where user can select these options is when service is configured for anonymous access. If service is configured for windows security, then using these two options will result in an exception
Identification – Service can get client’s identity but can not impersonate. If service tries to impersonate, an exception will be thrown.
Impersonation – Service can get client’s identity and can also impersonate it. Service will not be allowed to impersonate and access resources on different machines using client identity as service machine does not have client’s password
Delegation – Service gets client’s Kerberos ticket. Service can access resources on any machine as client. Service can propagate client’s identity down the call chain. Cloaking is used to propagate the caller identity along call chain.
1: SampleContractClient serviceProxy = new SampleContractClient( ); 2: serviceProxy.ClientCredentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Identification; 3: serviceProxy.SampleServiceOperation( ); 4: serviceProxy.Close( ); 5:
1: <client> 2: <endpoint behaviorConfiguration = "SampleImpersonationBehavior" 3: ... 4: /> 5: </client> 6: <behaviors> 7: <endpointBehaviors> 8: <behavior name = "SampleImpersonationBehavior"> 9: <clientCredentials> 10: <windows allowedImpersonationLevel = "Identification"/> 11: </clientCredentials> 12: </behavior> 13: </endpointBehaviors> 14: </behaviors> 15:
-
As a common design recommendation, the further from the client, the less significant its identity should be. In a layered architecture, each layer should run underneath its own identity, authenticate its direct callers, and implicitly trust its calling layer to authenticate its original callers.
Impersonation works directly opposite of this design guideline. Using impersonation also hinders scalability because several resources are allocated per identity. With impersonation, you will need as many resources as clients, and you will not be able to benefit from resource pooling mechanisms. Impersonation also makes resources administration complex. Also, if you rely on impersonation, it prohibits usage of non windows authentication mechanisms. If you do choose to use impersonation, use it carefully and only as a last resort when there is no other and better design approach.
Please feel free to email me with any questions you might have related to this topic. I’ll try to answer your queries to best of my knowledge. My email id is gauravsh@microsoft.com.
Happy Coding!
Gaurav Sharma ( gauravsh@microsoft.com
) Microsoft Information Security Tools (IST) Team Software Developer Engineer