IIS + Win Auth + Impersonation

Topics: Technical Questions
Dec 3, 2008 at 1:26 AM
I have been trying implement impersonation by using a custom policy. Unfortunately I have not been successful. 

I have seen a few posts here that have some pieces of the puzzle, but it seems that a lot of conversations happen offline and I think some important pieces may have been omitted.

Could I trouble someone to give some explicit instructions on how this can be achieved (IE Policy, Binding and code).

I have spent too many hours on this.
Dec 4, 2008 at 1:35 PM
I'm in the same position as Dave, I've spent hours trying to create a secure virtual service facade that requires authentication and includes message security.

I've still not got there and had to point consumers to my concrete service in the interim - which has to be a short term solution.

Please can we have a step by step guide similar to some of the excelent ones that are installed with mse.

Kenny Grant
Developer
Dec 5, 2008 at 2:25 PM
We'll work on getting a sample out so you'll be able to see a more complete picture of how to do things.  We really haven't put much out on security guidance and are working to correct this.  We appreciate your interest in this solution and will do our best to help ease the learning curve in this area.  We'll try to have something in a few days.
Dec 8, 2008 at 8:10 PM
Great news. MSE is becoming the backbone to our SOA strategy - the complete picture will be invaluable to us.
Developer
Dec 11, 2008 at 2:44 AM
The MSE Security Guide has now been added to the current June 2008 CTP release of the MSE.  This guide comes as both a document (XPS & PDF formats) along with sample source code implementing all the examples shown in the guide.  This is the initial release so we are very interested in feedback.  In addition we plan to add an end-to-end sample of at least one of the examples discussed in the guide.

Enjoy!
Dec 11, 2008 at 2:51 AM
Thanks Botto, I will have a look at it now.
Dec 17, 2008 at 12:04 AM
Thanks Botto, the content of the new security guide is fantastic and I have a successful implement at last. Yeah!!!

I have tweaked your IdentityAwareChannelElement sample files to construct my pure windows authentication impersonation channel policy. I had to move the impersonation process in the ChannelInitilizer from the opened event to opening, otherwise I found that either the runtime service account or the first client would always be used.

As my scenario is a departure from those discussed directly in the guide, I will include my code for anyone else who may have a windows auth environment.

Thanks Again!
Dave

<

 

PolicyModel xmlns="http://microsoft.com/mse/2007/runtime/policyModel"
xmlns:mse="clr-namespace:Microsoft.MSE.Runtime.Services.Behaviors;assembly=Microsoft.MSE.Runtime.Services"
xmlns:mse="http://services.microsoft.com/MSE"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wcf="clr-namespace:System.ServiceModel.Configuration;assembly=System.ServiceModel"
xmlns:myo="clr-namespace:MyOrg.ServiceModel.Configuration;assembly=MyOrg.ServiceModel.Configuration.WindowsImpersonationBehaviorExtension">
<
myo:WindowsImpersonationChannelElement></myo:WindowsImpersonationChannelElement>
<
mse:ChannelEndpointBehaviorExtension></mse:ChannelEndpointBehaviorExtension>
</
PolicyModel>

 


namespace

 

MyOrg.ServiceModel.Configuration

 

{

 

using System;

 

 

using System.ServiceModel;

 

 

using System.ServiceModel.Configuration;

 

 

using System.ServiceModel.Description;

 

 

using System.ServiceModel.Dispatcher;

 

 

using System.Security.Principal;

 

 

 

public class WindowsImpersonationChannelBehavior : IEndpointBehavior

 

{

 

//store settings from the policy xaml

 

 

private IWindowsImpersonationChannelSettings settings;

 

 

public WindowsImpersonationChannelBehavior(IWindowsImpersonationChannelSettings settings)

 

{

 

this.settings = settings;

 

}

 

public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)

 

{

 

ClientCredentials creds = null;

 

bindingParameters.Remove<

ClientCredentials>();

 

creds =

new ClientCredentials();

 

creds.Windows.AllowedImpersonationLevel = System.Security.Principal.

TokenImpersonationLevel.Impersonation;

 

bindingParameters.Add(creds);

}

 

public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)

 

{

clientRuntime.ChannelInitializers.Add(

new WindowsImpersonationChannelInitializer());

 

endpoint.Contract.SessionMode =

SessionMode.Allowed;

 

}

 

public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher) { }

 

 

public void Validate(ServiceEndpoint endpoint) { }

 

 

 

}

 

public class WindowsImpersonationChannelElement : BehaviorExtensionElement, IWindowsImpersonationChannelSettings

 

{

 

//add any required properties from the settings interface here

 

 

public WindowsImpersonationChannelElement()

 

:

base()

 

{

 

//establish default values for configurable properties

 

}

 

public override Type BehaviorType

 

{

 

get { return typeof(WindowsImpersonationChannelBehavior); }

 

}

 

protected override object CreateBehavior()

 

{

 

return new WindowsImpersonationChannelBehavior(this);

 

}

}

 

 

 

internal class WindowsImpersonationChannelInitializer : IChannelInitializer

 

{

 

private WindowsImpersonationContext impCtx;

 

 

 

public void Initialize(IClientChannel channel)

 

{

 

if (null != channel)

 

{

 

//use channel.opening for establishing impersonation context as if you wait for

 

 

// channel.opened, then you will see runtime account impersonation or

 

 

// the first caller will be used for all requests

 

channel.Opening +=

new EventHandler(this.Channel_Opening);

 

channel.Closed +=

new EventHandler(this.Channel_Closed);

 

}

}

 

 

private void Channel_Opening(object sender, EventArgs e)

 

{

 

ServiceSecurityContext sctx = ServiceSecurityContext.Current;

 

 

if (null != sctx)

 

{

 

WindowsIdentity clientIdentity = sctx.WindowsIdentity;

 

 

// only attempt impersonation if we have proper clearance

 

 

if (null != clientIdentity

 

&& (clientIdentity.ImpersonationLevel ==

TokenImpersonationLevel.Impersonation

 

|| clientIdentity.ImpersonationLevel ==

TokenImpersonationLevel.Delegation))

 

{

 

this.impCtx = clientIdentity.Impersonate();

 

}

}

}

 

 

private void Channel_Closed(object sender, EventArgs e)

 

{

 

try

 

{

 

if (null != this.impCtx)

 

{

 

this.impCtx.Undo();

 

}

}

 

catch { }

 

}

}

 

 

 

/// <summary>

 

 

/// This interface controls the availability of configuration properties in the policy xaml

 

 

/// </summary>

 

 

public interface IWindowsImpersonationChannelSettings

 

{

 

//add new settings properties here

 

}

}