fix(security): AutoLoginAuthenticationHandler no-op sign-in/out (avoid 500 on /auth/logout when flag on)

This commit is contained in:
Joseph Doherty
2026-06-11 04:45:29 -04:00
parent 82fec753c8
commit 2ad1dbc894
2 changed files with 26 additions and 2 deletions
@@ -15,7 +15,7 @@ namespace ZB.MOM.WW.OtOpcUa.Security.Auth;
/// The minted principal mirrors the shape the real login (AuthEndpoints) produces.
/// </summary>
public sealed class AutoLoginAuthenticationHandler
: AuthenticationHandler<AuthenticationSchemeOptions>
: AuthenticationHandler<AuthenticationSchemeOptions>, IAuthenticationSignInHandler
{
private readonly AuthDisableLoginOptions _opts;
@@ -32,6 +32,12 @@ public sealed class AutoLoginAuthenticationHandler
: base(options, logger, encoder)
=> _opts = disableLoginOptions.Value;
/// <summary>No-op: auto-login writes no cookie, so an explicit sign-in has nothing to persist.</summary>
public Task SignInAsync(ClaimsPrincipal user, AuthenticationProperties? properties) => Task.CompletedTask;
/// <summary>No-op: there is no auth cookie to clear; the next request re-authenticates via this handler.</summary>
public Task SignOutAsync(AuthenticationProperties? properties) => Task.CompletedTask;
/// <inheritdoc />
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
{
@@ -1,3 +1,4 @@
using System.Security.Claims;
using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
@@ -12,7 +13,7 @@ namespace ZB.MOM.WW.OtOpcUa.Security.Tests;
public class AutoLoginAuthenticationHandlerTests
{
private static async Task<AuthenticateResult> AuthenticateAsync(string user = "multi-role-test")
private static async Task<AutoLoginAuthenticationHandler> BuildHandlerAsync(string user = "multi-role-test")
{
var schemeOpts = new StubOptionsMonitor<AuthenticationSchemeOptions>(new AuthenticationSchemeOptions());
var disableOpts = Options.Create(new AuthDisableLoginOptions { DisableLogin = true, User = user });
@@ -23,6 +24,12 @@ public class AutoLoginAuthenticationHandlerTests
new AuthenticationScheme(
CookieAuthenticationDefaults.AuthenticationScheme, null, typeof(AutoLoginAuthenticationHandler)),
new DefaultHttpContext());
return handler;
}
private static async Task<AuthenticateResult> AuthenticateAsync(string user = "multi-role-test")
{
var handler = await BuildHandlerAsync(user);
return await handler.AuthenticateAsync();
}
@@ -48,6 +55,17 @@ public class AutoLoginAuthenticationHandlerTests
result.Principal!.Identity!.Name.ShouldBe("custom-dev");
}
[Fact]
public async Task SignIn_and_SignOut_are_noops_and_do_not_throw()
{
var handler = await BuildHandlerAsync();
await Should.NotThrowAsync(async () =>
{
await ((IAuthenticationSignInHandler)handler).SignInAsync(new ClaimsPrincipal(), null);
await ((IAuthenticationSignOutHandler)handler).SignOutAsync(null);
});
}
/// <summary>
/// Minimal <see cref="IOptionsMonitor{TOptions}"/> stub returning a fixed value for any
/// name. The test project does not reference Moq, so the scheme-options monitor the base