question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

System.InvalidOperationException: No authentication handler is registered for the scheme 'Negotiate'. The registered schemes are: Windows. Did you forget to call AddAuthentication().Add[SomeAuthHandler]("Negotiate",...)

See original GitHub issue

We’re using transport Windows authentication.

Client: ((BasicHttpsBinding)binding).Security.Mode = BasicHttpsSecurityMode.Transport; ((BasicHttpsBinding)binding).Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;

Server: var builder = WebApplication.CreateBuilder(args);

// Add services to the container. builder.Services.AddServiceModelServices(); builder.Services.AddServiceModelMetadata();

builder.Services.AddServiceModelConfigurationManagerFile(“wcf.config”);

builder.Services.AddAuthentication(IISDefaults.AuthenticationScheme); builder.Services.AddAuthorization(); builder.Services.AddHttpContextAccessor();

builder.Services.AddSingleton<IServiceBehavior, UseRequestHeadersForMetadataAddressBehavior>();

Up to version 1.1.0-alpha.35, it was working without error. After alpha.35, the error we receive is:

System.InvalidOperationException: No authentication handler is registered for the scheme ‘Negotiate’. The registered schemes are: Windows. Did you forget to call AddAuthentication().AddSomeAuthHandler? at Microsoft.AspNetCore.Authentication.AuthenticationService.AuthenticateAsync(HttpContext context, String scheme) at CoreWCF.Channels.RequestDelegateHandler.HandleRequest(HttpContext context) at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) at CoreWCF.Channels.ServiceModelHttpMiddleware.InvokeAsync(HttpContext context) at CoreWCF.Channels.MetadataMiddleware.InvokeAsync(HttpContext context) at Microsoft.AspNetCore.Builder.Extensions.UsePathBaseMiddleware.InvokeCore(HttpContext context, PathString matchedPath, PathString remainingPath) at Microsoft.AspNetCore.Server.IIS.Core.IISHttpContextOfT`1.ProcessRequestAsync()

Issue Analytics

  • State:open
  • Created a year ago
  • Comments:13 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
mvarblowcommented, Mar 19, 2023

In case it helps, here’s a complete walkthrough showing how to reproduce this problem. It’s fairly simple and just boils down to this: a .NET Framework WCF client app is not able to call a CoreWCF server app that requires Windows authentication – unless the client changes the default impersonation mode from Identification to Delegate or None.

This repo includes the completed demo: https://github.com/mvarblow/CoreWcfAuthDemo

Create the CoreWCF app which requires Windows authentication

dotnet new corewcf --name CoreWCFDemoServer --framework net7.0
cd CoreWCFDemoServer
dotnet add package Microsoft.AspNetCore.Authentication.Negotiate

Add authentication and authorization services in Program.cs:

builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme).AddNegotiate();
builder.Services.AddAuthorization();

Replace this line:

    serviceBuilder.AddServiceEndpoint<Service, IService>(new BasicHttpBinding(BasicHttpSecurityMode.Transport), "/Service.svc");

With these three lines:

    var binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
    binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
    serviceBuilder.AddServiceEndpoint<Service, IService>(binding, "/Service.svc");

Add [Authorize] attribute to Service.GetData method in IService.cs

        [Authorize]
        public string GetData(int value)

Start debugging in VS. Copy the service WSDL URL, e.g. https://localhost:7209/service.svc?wsdl

Create a .NET 7 Client Application

Create a new console application: dotnet new console --name CoreWCFDemoClient --framework net7.0

Right-click on the project in VS and use Add > Service Reference. Pick WCF Web Service. Paste in the service URL for the running Core WCF service. Click through the rest of the wizard.

Add this to the CoreWCFDemoClient Program.cs:

var client = new ServiceReference1.ServiceClient();
client.ClientCredentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials;
Console.WriteLine(await client.GetDataAsync(12));

Run the client. It should print:

Hello, World!
You entered: 12

Create a .NET Framework Client Application

Now, create a .NET Framework console application from Visual Studio. Again, right-click on the project, Add Service Reference. Paste in the service WSDL URL and complete the dialog. In Program.cs add the following to the Main method:

            var client = new ServiceReference1.ServiceClient();
            client.ClientCredentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials;
            Console.WriteLine(client.GetData(12));

Run the legacy client. It should print:

You entered: 12

Everything works fine as long as you run the CoreWCF service from the command line using Kestrel.

Host the Core WCF Server in IIS

Stop running CoreWCFDemoServer. Now let’s deploy it to IIS. Publish the CoreWCFDemoServer project to a folder. In IIS, create a new site using the publish folder as the physical path. Use the same port number that was previously used for running CoreWCFDemoServer from Visual Studio.

image

Change the site’s app pool to “No managed code”.

image

Enable Windows Authentication and disable Anonymous Authentication for the CoreWCFDemoServer site in IIS Manager.

image

Now run the CoreWCFDemoClient. It should again run successfully and print:

Hello, World!
You entered: 12

Now run the LegacyWCFClient. It will fail.

Unhandled Exception: System.ServiceModel.Security.MessageSecurityException: The HTTP request is unauthorized with client authentication scheme 'Negotiate'. The authentication header received from the server was 'Negotiate,NTLM'. ---> System.Net.WebException: The remote server returned an error: (401) Unauthorized.
   at System.Net.HttpWebRequest.GetResponse()
   at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
   --- End of inner exception stack trace ---

Server stack trace:
   at System.ServiceModel.Channels.HttpChannelUtilities.ValidateAuthentication(HttpWebRequest request, HttpWebResponse response, WebException responseException, HttpChannelFactory`1 factory)
   at System.ServiceModel.Channels.HttpChannelUtilities.ValidateRequestReplyResponse(HttpWebRequest request, HttpWebResponse response, HttpChannelFactory`1 factory, WebException responseException, ChannelBinding channelBinding)
   at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
   at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Exception rethrown at [0]:
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   at LegacyWcfClient.ServiceReference1.IService.GetData(Int32 value)
   at LegacyWcfClient.ServiceReference1.ServiceClient.GetData(Int32 value) in C:\Temp\Code\CoreWcfAuthDemo\LegacyWcfClient\Connected Services\ServiceReference1\Reference.cs:line 122
   at LegacyWcfClient.Program.Main(String[] args) in C:\Temp\Code\CoreWcfAuthDemo\LegacyWcfClient\Program.cs:line 15

If you change the allowed impersonation level in the LegacyWCFClient to None or Delegation before calling the service then the call succeeds, e.g.

            client.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Delegation;

or

           client.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.None;

But with the default value it fails:

            client.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Identification;

Summary

With a CoreWCF service configured to require Windows authentication, .NET Core clients work fine. But .NET Framework clients fail if using the default impersonation level.

It appears that Windows authentication is working successfully in IIS. We can see the successful authentication events in the security event log. But it appears that Microsoft.AspNetCore.Authentication.Negotiate does not flow the user principle over into ASP.NET Core / CoreWCF?

This is preventing us from successfully porting our application, which has legacy callers which need to continue working with the new service. The legacy callers use the default impersonation level.

1reaction
dandesro71commented, Aug 17, 2022

It solved the problem when the client is using:

        client.ChannelFactory.Credentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Delegation;

or client.ChannelFactory.Credentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.None;

The default is TokenImpersonationLevel.Identification. The error received in the client is:

System.ServiceModel.Security.MessageSecurityException: ‘The HTTP request is unauthorized with client authentication scheme ‘Negotiate’. The authentication header received from the server was ‘Negotiate,NTLM’.’

I cannot ask to all the clients to modify their code to use TokenImpersonationLevel.None . I’m sure this is only something missing in my service configuration. Once again, it was working properly up to version 1.1.0-alpha.35.

Read more comments on GitHub >

github_iconTop Results From Across the Web

No authentication handler is registered for the scheme ...
"InvalidOperationException: No authentication handler is registered for the scheme 'CookieSettings'. The registered schemes are: Identity.
Read more >
No authentication handler is registered for the scheme ' ...
The error appears with this stack. System.InvalidOperationException: No authentication handler is registered for the scheme 'Identity.
Read more >
No Sign-in Authentication handler is registered for the scheme ...
InvalidOperationException : No sign-in authentication handler is registered for the scheme 'Cookies'. The registered sign-in schemes are: ...
Read more >
Authorize with a specific scheme in ASP.NET Core
This article explains how to limit identity to a specific scheme when working with multiple authentication methods.
Read more >
Trouble Implementing Auth0 No authentication handlers ...
On ASP.NET Core MVC app. “InvalidOperationException: No authentication handlers are registered. Did you forget to call AddAuthentication().
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found