Files
natsdotnet/tests/NATS.Server.Tests/Auth/ExternalAuthCalloutTests.cs
2026-02-23 13:08:52 -05:00

59 lines
2.0 KiB
C#

using NATS.Server.Auth;
using NATS.Server.Protocol;
namespace NATS.Server.Tests;
public class ExternalAuthCalloutTests
{
[Fact]
public void External_callout_authenticator_can_allow_and_deny_with_timeout_and_reason_mapping()
{
var authenticator = new ExternalAuthCalloutAuthenticator(
new FakeExternalAuthClient(),
TimeSpan.FromMilliseconds(50));
var allowed = authenticator.Authenticate(new ClientAuthContext
{
Opts = new ClientOptions { Username = "u", Password = "p" },
Nonce = [],
});
allowed.ShouldNotBeNull();
allowed.Identity.ShouldBe("u");
var denied = authenticator.Authenticate(new ClientAuthContext
{
Opts = new ClientOptions { Username = "u", Password = "bad" },
Nonce = [],
});
denied.ShouldBeNull();
var timeout = new ExternalAuthCalloutAuthenticator(
new SlowExternalAuthClient(TimeSpan.FromMilliseconds(200)),
TimeSpan.FromMilliseconds(30));
timeout.Authenticate(new ClientAuthContext
{
Opts = new ClientOptions { Username = "u", Password = "p" },
Nonce = [],
}).ShouldBeNull();
}
private sealed class FakeExternalAuthClient : IExternalAuthClient
{
public Task<ExternalAuthDecision> AuthorizeAsync(ExternalAuthRequest request, CancellationToken ct)
{
if (request is { Username: "u", Password: "p" })
return Task.FromResult(new ExternalAuthDecision(true, "u", "A"));
return Task.FromResult(new ExternalAuthDecision(false, Reason: "denied"));
}
}
private sealed class SlowExternalAuthClient(TimeSpan delay) : IExternalAuthClient
{
public async Task<ExternalAuthDecision> AuthorizeAsync(ExternalAuthRequest request, CancellationToken ct)
{
await Task.Delay(delay, ct);
return new ExternalAuthDecision(true, "slow");
}
}
}