views:

189

answers:

0

I have a WPF client that connects to a set of WCF web services. We have a Dev, Test, Volume and Production domains, with the services available on a server in each domain. The domains do not have trust relationships.

The goal is to have the client connect the the services of any other domain. If the client and server are on the same domain then the Default Network Credentials should be sent to authenticate/authorize. If the server is in a different domain, then it should challenge the user for credentials, much in the same way Internet Explorer does when you hit a site on a different domain with Integrated Security set.

At the moment i'm trying to fetch the clients credentials by setting DisplayInitializationUI() when creating an instance of the ClientBase for my service.

Client client = new Client(); // <- the wcf ClientBase implementation for the serivce.
client.Endpoint.Behaviors.Remove<ClientCredentials>();
client.Endpoint.Behaviors.Add<ClientCredentialsEx>();
client.DisplayInitializationUI();
client.InnerChannel.Open();

The ClientCredentialsEx class.

public class ClientCredentialsEx : ClientCredentials
{
    public ClientCredentialsEx() : base() { }
    public ClientCredentialsEx(ClientCredentialsEx other) : base(other) { }

    public override void ApplyClientBehavior(ServiceEndpoint serviceEndpoint, ClientRuntime behavior)
    {
        behavior.InteractiveChannelInitializers.Add(new ShowCredentialUI());
        base.ApplyClientBehavior(serviceEndpoint, behavior);
    }
    protected override ClientCredentials CloneCore()
    {
        return new ClientCredentialsEx(this);
    }
}

The ShowCredentialUI class implements IInteractiveChannelInitializer. The business end of the class is the BeginDisplayInitializationUI method;

public IAsyncResult BeginDisplayInitializationUI(IClientChannel channel, AsyncCallback callback, object state)
{
    string host = "";
    CREDUI_INFO info = new CREDUI_INFO();
    string username = string.Empty, password = string.Empty;

    CREDUI_FLAGS flags = CREDUI_FLAGS.GENERIC_CREDENTIALS |
                         CREDUI_FLAGS.SHOW_SAVE_CHECK_BOX |
                         CREDUI_FLAGS.EXPECT_CONFIRMATION;

    bool savePwd = false;

    // PromptForCredentials calls interop credui to challenge the user for username/password/smartcard.
    CredUIReturnCodes result = PromptForCredentials(ref info, host, 0, ref username,
                                                      ref password, ref savePwd, flags);


    ChannelParameterCollection collection = channel.GetProperty<ChannelParameterCollection>();
    collection.Add(new NetworkCredential(username, password));
    return new AsyncResult();
}

The problem is when I investigate the iis logs, the credentials are never sent. I suspect that I am missing something crucial. Has anyone had a similar scenario implemented successfully? Is there an easier way to achieve this?

Thanks for reading!

related questions