Move 50 auth/accounts/permissions/JWT/NKey test files from NATS.Server.Tests into a dedicated NATS.Server.Auth.Tests project. Update namespaces, replace private GetFreePort/ReadUntilAsync helpers with TestUtilities calls, replace Task.Delay with TaskCompletionSource in test doubles, and add InternalsVisibleTo. 690 tests pass.
62 lines
2.3 KiB
C#
62 lines
2.3 KiB
C#
using NATS.Server.Auth;
|
|
using NATS.Server.Protocol;
|
|
|
|
namespace NATS.Server.Auth.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)
|
|
{
|
|
var tcs = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
|
|
await using var reg = ct.Register(() => tcs.TrySetCanceled(ct));
|
|
using var timer = new Timer(_ => tcs.TrySetResult(true), null, delay, Timeout.InfiniteTimeSpan);
|
|
await tcs.Task;
|
|
return new ExternalAuthDecision(true, "slow");
|
|
}
|
|
}
|
|
}
|