Bug 2415 - When calling a WCF service with windows authentication a client credentials exception is thrown
Summary: When calling a WCF service with windows authentication a client credentials e...
Status: NEW
Alias: None
Product: Class Libraries
Classification: Mono
Component: WCF assemblies (show other bugs)
Version: unspecified
Hardware: Macintosh Mac OS
: --- normal
Target Milestone: Untriaged
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2011-12-08 06:18 UTC by Dave
Modified: 2011-12-29 15:27 UTC (History)
1 user (show)

Tags:
Is this bug a regression?: ---
Last known good build:


Attachments
Modified copies of the BasicHttpBinding and HttpRequestChannel classes (8.41 KB, patch)
2011-12-27 16:22 UTC, Dave
Details
BasicHttpBinding and HttpRequestChannel patch (3.94 KB, patch)
2011-12-29 15:27 UTC, Dave
Details


Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report for Bug 2415 on GitHub or Developer Community if you have new information to add and do not yet see a matching new report.

If the latest results still closely match this report, you can use the original description:

  • Export the original title and description: GitHub Markdown or Developer Community HTML
  • Copy the title and description into the new report. Adjust them to be up-to-date if needed.
  • Add your new information.

In special cases on GitHub you might also want the comments: GitHub Markdown with public comments

Related Links:
Status:
NEW

Description Dave 2011-12-08 06:18:18 UTC
We have a basicHttpBinding WCF web service with windows authenctication configured. A dynamic proxy is generated from an Interface to call the web service's functions.

On a Windows machine using the following code, using .net framework 3.5, the following will succeed.

if (connection.UseAuthentication)
{
                //do some crazy authentication malarkey
    binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
 binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
}


String hostAddress = String.Format("{0}/Management.svc", connection.Server);
EndpointAddress newAddress = new EndpointAddress(hostAddress);

ChannelFactory<AccessMobileServices.IManagement>  ManagementChannel = new ChannelFactory<AccessMobileServices.IManagement>(binding);

if (connection.UseAuthentication)
{

                    ManagementChannel.Credentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;

ManagementChannel.Credentials.Windows.AllowNtlm = true;
ManagementChannel.Credentials.Windows.ClientCredential = new NetworkCredential("USERNAME", "PASSWORD", "DOMAIN");

}

ManagementProxy = ManagementChannel.CreateChannel(newAddress);

m_Database = connection.Database;

SecurityTicketRequest request = new SecurityTicketRequest();
request.Username = connection.Username;
request.Password = connection.Password;
request.Database = connection.Database;
request.APIKey = Access.Mobile.Datatypes.Keys.ApiKeys.WebServiceAPIKey;

SecurityTicketResponse result = ManagementProxy.CreateSecurityTicket(request);

However, when the same code is run via mono on a mac(either as a compiled dll or as source files) an exception is thrown.

The exception message is 
Use ClientCredentials to specify a user name for required HTTP negotiate authentication.

Setting the client credentials

ManagementChannel.Credentials.UserName.UserName = @"DOMAIN\USERNAME";
ManagementChannel.Credentials.UserName.Password = "PASSWORD";

removes the error but always returns failed authentication, regardless of the combination of username and password.


Details:
Mac OSX Lion using monodevelop 2.8.2

Mono JIT compiler version 2.10.6 (tarball Fri Sep 16 00:13:06 EDT 2011)
Copyright (C) 2002-2011 Novell, Inc, Xamarin, Inc and Contributors. www.mono-project.com
	TLS:           normal
	SIGSEGV:       normal
	Notification:  kqueue
	Architecture:  x86
	Disabled:      none
	Misc:          debugger softdebug 
	LLVM:          yes(2.9svn-mono)
	GC:            Included Boehm (with typed GC)

Service Config
<basicHttpBinding>
        <binding name="Basic" maxBufferSize="655360000" maxReceivedMessageSize="655360000" maxBufferPoolSize="655360000">
          <readerQuotas maxStringContentLength="655360000" maxArrayLength="655360000" maxBytesPerRead="655360000" maxNameTableCharCount="655360000" maxDepth="100"/>
          <!-- Enable the section below to support Windows authentication on the http connection-->

          <security mode="TransportCredentialOnly">
            <transport clientCredentialType="Windows"/>
          </security>
         
        </binding>
      </basicHttpBinding>

IIS 7.5(windows 7)
Anonymous disabled
Windows Authentication disabled
Comment 1 Zoltan Varga 2011-12-08 08:10:20 UTC
-> wcf.
Comment 2 Dave 2011-12-27 16:22:52 UTC
Created attachment 1101 [details]
Modified copies of the BasicHttpBinding and HttpRequestChannel classes

I have done some work on this bug using the source code from the main branch.

By setting the authenticationscheme of the binding(BasicHttpBinding) to IntegratedWindows when client credential type is set to Windows you can set the HttpRequestChannel to pass the NetworkCredentials from the windows property of the ClientCredntials.  This allows the user to specify domain as well as username and password.

The changes are below.

BasicHttpBinding.cs

Original

switch (Security.Transport.ClientCredentialType) {
case HttpClientCredentialType.Basic:
h.AuthenticationScheme = AuthenticationSchemes.Basic;
break;
case HttpClientCredentialType.Ntlm:
h.AuthenticationScheme = AuthenticationSchemes.Ntlm;
break;
case HttpClientCredentialType.Windows:
h.AuthenticationScheme = AuthenticationSchemes.Negotiate;
break;

New

switch (Security.Transport.ClientCredentialType) 
{
	case HttpClientCredentialType.Basic:
		h.AuthenticationScheme = AuthenticationSchemes.Basic;
				break;
	case HttpClientCredentialType.Ntlm:
		h.AuthenticationScheme = AuthenticationSchemes.Ntlm;
				break;
	case HttpClientCredentialType.Windows:
               h.AuthenticationScheme  = AuthenticationSchemes.IntegratedWindowsAuthentication;

HttpRequestChannel

Original

var httpbe = (HttpTransportBindingElement) source.Transport;
string authType = null;
switch (httpbe.AuthenticationScheme) {
// AuthenticationSchemes.Anonymous is the default, ignored.
case AuthenticationSchemes.Basic:
authType = "Basic";
break;
case AuthenticationSchemes.Digest:
authType = "Digest";
break;
case AuthenticationSchemes.Ntlm:
authType = "Ntlm";
break;
case AuthenticationSchemes.Negotiate:
authType = "Negotiate";
break;
}
if (authType != null) {
var cred = source.ClientCredentials;
string user = cred != null ? cred.UserName.UserName : null;
string pwd = cred != null ? cred.UserName.Password : null;
if (String.IsNullOrEmpty (user))
throw new InvalidOperationException (String.Format ("Use ClientCredentials to specify a user name for required HTTP {0} authentication.", authType));
var nc = new NetworkCredential (user, pwd);
web_request.Credentials = nc;
// FIXME: it is said required in SL4, but it blocks full WCF.
//web_request.UseDefaultCredentials = false;
}

New

var httpbe = (HttpTransportBindingElement) source.Transport;
			string authType = null;
			switch (httpbe.AuthenticationScheme) {
			// AuthenticationSchemes.Anonymous is the default, ignored.
			case AuthenticationSchemes.Basic:
				authType = "Basic";
				break;
			case AuthenticationSchemes.Digest:
				authType = "Digest";
				break;
			case AuthenticationSchemes.Ntlm:
				authType = "Ntlm";
				break;
			case AuthenticationSchemes.Negotiate:
				authType = "Negotiate";
				break;
			case AuthenticationSchemes.IntegratedWindowsAuthentication:
				authType = "Negotiate";
				break;
			}

			if (authType != null)
            		{
              			NetworkCredential netCred = null;
 
		                if (httpbe.AuthenticationScheme == AuthenticationSchemes.IntegratedWindowsAuthentication)
                		{
                    			netCred = source.ClientCredentials.Windows.ClientCredential;
                    
		                }
                		else
                		{
		                    var cred = source.ClientCredentials;
                		    string user = cred != null ? cred.UserName.UserName : null;
                    		    string pwd = cred != null ? cred.UserName.Password : null;
                    		    if (String.IsNullOrEmpty(user))
                        		throw new InvalidOperationException(String.Format("Use ClientCredentials to specify a user name for required HTTP {0} authentication.", authType));
                    		    netCred = new NetworkCredential(user, pwd);
                		}
                		web_request.Credentials = netCred;
                		// FIXME: it is said required in SL4, but it blocks full WCF.
                		//web_request.UseDefaultCredentials = false;
            		}
Comment 3 Dave 2011-12-29 15:27:25 UTC
Created attachment 1111 [details]
BasicHttpBinding and HttpRequestChannel patch

Patch file to enable windows authentication to work when using BasicHttpBinding with a WCF Service