Using Windsor Castle and WcfFacility to create WCF proxies with Message Security and username credentials

2.1k views Asked by At

OK we are using message security with username credentials (and X509 certificate encryption) to communicate with our WCF service. I am not happy with this approach but that is not the point of question and I do not want to get into that.

I am using Windsor Castle to generate proxies in ASP NET Web Forms + MVC hybrid. We are using forms authentication and use user's credentials to communicate with WCF services - this will help auditing all calls. As I said, I am not happy with this approach but that is not the point.

I have created CustomCredentials class which inherits AbstractCredentials class and WcfFacility happily uses it to configure my proxies. As you will see below, all my setup is just a few lines. I have created unit test below which demonstrates all I am doing: creating a proxy, making a call and then releasing it in a loop. Now I am expecting this test to work but it does not and I get

Expected: 10 But was: 1

I have not included binding but that is irrelevant, as I said I am using Message Security with X509 certificates.

I know that for channel factory with message security, once opened you cannot change credentials. Is this the same issue?

Is this a bug in WcfFacility or a limitation?

Here is the code

[TestFixture]
public class Harness
{

    private IWindsorContainer _container;
    public static int NumberOfTimesCredentialsConfigured = 0;

    [SetUp]
    public void Setup()
    {
        _container = new WindsorContainer().AddFacility<WcfFacility>();

    Component
        .For<IFrameworkUsers>()
        .ActAs(DefaultClientModel
        .On(WcfEndpoint.FromConfiguration("FrameworkUsersService"))
        .Credentials(new CustomCredentials()))
        .LifeStyle.Transient);
    }

    [Test]
    public void MultipleProxyTest()
    {

        const int Runs = 10;
        NumberOfTimesCredentialsConfigured = 0;
        for (int i = 0; i < Runs; i++)
        {
            IFrameworkUsers frameworkUsers = _container.Resolve<IFrameworkUsers>();
            frameworkUsers.CreateUserSession();
            _container.Release(frameworkUsers);
        }

        Assert.AreEqual(Runs, NumberOfTimesCredentialsConfigured);
                    // FAILS!!! Expected: 10  But was:  1
    }

    [TearDown]
    public void TearDown()
    {

    }


}

public class CustomCredentials : AbstractCredentials
{


    #region Overrides of AbstractCredentials

    protected override void ConfigureCredentials(ClientCredentials credentials)
    {
        credentials.UserName.UserName = "testuser";
        credentials.UserName.Password = "abcdef";

        Harness.NumberOfTimesCredentialsConfigured++;
    }

    #endregion
} 
2

There are 2 answers

0
Aliostad On BEST ANSWER

I posted on castle forum and no reply. It is a problem by design in WCF Facility in which they cache service channels which is OK with no security but does not work with security.

0
Ivan Danilov On

Your credentials and IWcfEndpoint in general (which is the result of DefaultClientModel.On(...) call) are created only once when the container is configured. If you want to provide different credentials each time - you need to make them dynamic dependency like below:

_container.Register(Component.For<IFrameworkUsers>()
    .AsWcfClient()
    .DependsOn(
        (k, d) => d["endpoint"] = 
            new DefaultClientModel(WcfEndpoint.FromConfiguration("FrameworkUsersService"))
                .Credentials(new CustomCredentials())
     )
    .LifeStyle.Transient);

String endpoint here is the name of dependency consumed by WcfFacility. I'm not sure where exactly, but it is resolved in some interceptor (you may set breakpoint in the lambda and debug your test to look at call stack). I assume it is made to match name of AsWcfClient(IWcfEndpoint endpoint) method argument.

So the answer is no, it is nor bug nor limitation of WcfFacility.