I have an ASP.NET Core web application, which I'm using to host a WCF Core service. This is my Program.cs:
using System.Text;
using CoreWCF;
using CoreWCF.Channels;
using CoreWCF.Configuration;
using CoreWCF.Description;
using Microsoft.AspNetCore.Authentication;
using WebApplication1;
const string HOST_IN_WSDL = "localhost";
var builder = WebApplication.CreateBuilder(args);
// Add WSDL support
builder.Services.AddServiceModelServices().AddServiceModelMetadata();
// Use the scheme/host/port used to fetch WSDL as that service endpoint address in generated WSDL
builder.Services.AddSingleton<IServiceBehavior, UseRequestHeadersForMetadataAddressBehavior>();
builder.Services.AddHttpContextAccessor();
builder.Services.AddAuthentication("MyScheme")
.AddScheme<AuthenticationSchemeOptions, MyAuthenticationHandler>("MyScheme", null);
builder.Services.AddAuthorization();
var app = builder.Build();
app.UseServiceModel(builder =>
{
builder.AddService(typeof(MyService), (serviceOptions) =>
{
serviceOptions.BaseAddresses.Add(new Uri($"https://{HOST_IN_WSDL}/MyService"));
})
.AddServiceEndpoint(typeof(MyService),
typeof(IMyService),
new WSHttpBinding(SecurityMode.Transport), // SOAP 1.2
new Uri("", UriKind.RelativeOrAbsolute), (Uri)null, null);
});
// Enable WSDL for http & https
var serviceMetadataBehavior = app.Services.GetRequiredService<ServiceMetadataBehavior>();
serviceMetadataBehavior.HttpGetEnabled = serviceMetadataBehavior.HttpsGetEnabled = true;
app.MapGet("/", () => "Hello World!");
app.UseAuthentication();
app.UseAuthorization();
app.Run();
MyService.cs:
internal class MyService : IMyService
{
public async Task<string> HelloWorld(string name)
{
await Task.Delay(1);
return $"Hello, {name}!";
}
}
IMyService.cs:
using CoreWCF;
[ServiceContract(Namespace = "http://schemas.test.com/myengine")]
public interface IMyService
{
[OperationContract(AsyncPattern = true)]
Task<string> HelloWorld(string name);
}
MyAuthenticationHandler.cs:
using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Options;
using System.Security.Claims;
using System.Text.Encodings.Web;
namespace WebApplication1
{
public class MyAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
public MyAuthenticationHandler(
IOptionsMonitor<AuthenticationSchemeOptions> options,
ILoggerFactory logger,
UrlEncoder encoder
)
: base(options, logger, encoder)
{
}
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
// Retrieve the current principal
var currentPrincipal = System.Web.HttpContext.Current.User;
// Create a ClaimsPrincipal if the current principal is not a ClaimsPrincipal
var claimsPrincipal = currentPrincipal as ClaimsPrincipal ?? new ClaimsPrincipal(currentPrincipal);
return AuthenticateResult.Success(new AuthenticationTicket(claimsPrincipal, Scheme.Name));
// return AuthenticateResult.Fail("Invalid credentials");
}
}
}
When I call my service with SoapUI, I get this error:
HTTP/1.1 500 Internal Server Error Content-Type: text/plain; charset=utf-8 Date: Wed, 06 Aug 2025 14:00:58 GMT Server: Kestrel Transfer-Encoding: chunked
System.InvalidOperationException: No authentication handler is registered for the scheme 'Negotiate'. The registered schemes are: MyScheme. 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.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)HEADERS ======= Connection: keep-alive Host: localhost:7075 User-Agent: Apache-HttpClient/4.5.5 (Java/17.0.12) Accept-Encoding: gzip,deflate Content-Type: application/soap+xml;charset=UTF-8;action="http://schemas.test.com/myengine/IMyService/HelloWorld" Content-Length: 432
I would like to handle authentication myself. What do I need to change to stop it from checking the Negotiate scheme?