Reputation: 5744
I'm using AspNetCore 2 with HTTP.SYS. I'm trying to implement an authentication scheme that
1. Performs custom (stateless) authentication if a request has a given header, or
2. If not, defaults back to windows auth
My initial attempt was adding a policy scheme that selects the appropriate authentication scheme based on the request. This doesn't quite work though - it looks that Http.sys authentication is done BEFORE my policy selector is even invoked (see comment in the code snippet).
In a desparate and clueless attempt, I've fiddled around with setting AllowAnonymous to true, but that just seems to lead to Windows auth never being used.
Is there any way to select the auth scheme properly?
var host = new WebHostBuilder()
.ConfigureServices(services =>
{
services
.AddAuthentication("DynamicAuthenticationScheme")
.AddScheme<AuthenticationSchemeOptions, CustomAuth>("Custom", _ => { })
.AddPolicyScheme("DynamicAuthenticationScheme", "Default system policy", cfgOptions =>
{
cfgOptions.ForwardDefaultSelector = ctx =>
{
// Auth looks to be done beforehand already; if setting a breakpoint here, ctx.User is already given
if (ctx.Request.Headers.ContainsKey("CUSTOM-AUTH"))
return "Custom";
return HttpSysDefaults.AuthenticationScheme;
};
});
})
.UseHttpSys(options =>
{
options.Authentication.Schemes = AuthenticationSchemes.NTLM | AuthenticationSchemes.Negotiate;
options.Authentication.AllowAnonymous = false;
})
.UseUrls("http://localhost:7200")
.Configure(app =>
{
app.UseAuthentication();
app.Map(new PathString("/test"), cfg =>
cfg.Use(async (context, next) =>
{
await context.Response.WriteAsync($"Hello {context.User.Identity?.Name}");
}));
})
.Build();
await host.StartAsync();
Upvotes: 0
Views: 231
Reputation: 5744
I've "solved" this now by adding a custom middleware:
class MyMiddleware : IMiddleware
{
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
if(ShouldUseCustomAuth(context))
{
var authResult = await context.AuthenticateAsync("Custom");
if(authResult.Succeeded)
{
context.User = auth.Principal;
await next(context);
return;
}
}
await context.ChallengeAsync("Windows");
}
}
I'll leave the question open for a moment though in case anyone has a nicer solution (maybe involving policies after all?)
Upvotes: 1