In WCF, for a webHttpBinding, how do I specify credentials in the client side web.config when the server is using basic authentication?

Steve Elmer picture Steve Elmer · Dec 18, 2009 · Viewed 12.8k times · Source

I have two WCF RESTful services - the "general" service is public and has no security; the "admin" service I intend to use basic authentication over SSL. This is my server side web.config:

<system.serviceModel>
    <bindings>
        <webHttpBinding>
            <binding name="general" maxReceivedMessageSize="2147483647">
                <readerQuotas maxArrayLength="2147483647" maxStringContentLength="2147483647" />
                <security mode="None">
                    <transport clientCredentialType="None" />
                </security>
            </binding>
            <binding name="admin" maxReceivedMessageSize="2147483647">
                <readerQuotas maxArrayLength="2147483647" maxStringContentLength="2147483647" />
                <security mode="Transport">
                    <transport clientCredentialType="Basic" />
                </security>
            </binding>
        </webHttpBinding>
    </bindings>
    <behaviors>
        <serviceBehaviors>
            <behavior>
                <serviceMetadata httpGetEnabled="true"/>
                <serviceDebug includeExceptionDetailInFaults="false"/>
            </behavior>
        </serviceBehaviors>
        <endpointBehaviors>
            <behavior name="web">
                <webHttp/>
            </behavior>
        </endpointBehaviors>
    </behaviors>
    <services>
        <service name="MyNamespace.AppServices.GeneralService">
            <endpoint address="" binding="webHttpBinding" contract="MyNamespace.Contracts.IGeneralService" behaviorConfiguration="web" bindingConfiguration="general" />
        </service>
        <service name="MyNamespace.AppServices.AdminService">
            <endpoint address="" binding="webHttpBinding" contract="MyNamespace.Contracts.IAdminService" behaviorConfiguration="web" bindingConfiguration="admin" />
        </service>
    </services>
</system.serviceModel>

On the client side, I currently have code that looks like this:

private static IGeneralService GetGeneralChannel()
{
    WebHttpBinding binding = new WebHttpBinding();
    binding.Security.Mode = WebHttpSecurityMode.None;
    binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
    binding.MaxReceivedMessageSize = Int32.MaxValue;
    binding.ReaderQuotas.MaxStringContentLength = Int32.MaxValue;
    binding.ReaderQuotas.MaxArrayLength = Int32.MaxValue;

    WebChannelFactory<IGeneralService> cf = new WebChannelFactory<IGeneralService>(binding, new Uri("http://localhost:1066/GeneralService"));
    IGeneralService channel = cf.CreateChannel();
    return channel;
}

private static IAdminService GetAdminChannel()
{
    WebHttpBinding binding = new WebHttpBinding();
    binding.Security.Mode = WebHttpSecurityMode.Transport;
    binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
    binding.MaxReceivedMessageSize = Int32.MaxValue;
    binding.ReaderQuotas.MaxStringContentLength = Int32.MaxValue;
    binding.ReaderQuotas.MaxArrayLength = Int32.MaxValue;

    WebChannelFactory<IAdminService> cf = new WebChannelFactory<IAdminService>(binding, new Uri("http://localhost:1066/AdminService"));
    cf.Credentials.UserName.UserName = "myUserName";
    cf.Credentials.UserName.Password = "myPassword";

    IAdminService channel = cf.CreateChannel();
    return channel;
}

The question is, since I obviously do not want to hard-code all of this configuration information, how do I need to provide it in the web.config on the client? It is pretty clear to me that the binding element needs to look pretty much the same on the client as it does on the server. However, where do I indicate the credentials that are assigned to the WebChannelFactory?

Any help and/or insight will be appreciated.

Thanks, Steve

Answer

marc_s picture marc_s · Dec 18, 2009

You cannot put those credentials (username and password) into web.config and have WCF read them from there. This is one of the very few features in WCF which cannot be done in config - you have to set those credentials in your code.

Of course, in your code, you can read them from e.g. a database table, or a config entry somewhere - but you have to do that yourself. WCF can't be configured to automagically read those settings from somewhere.