From 11dc5e62f37aebcf174d20fc8d85da1d58978ac1 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Sun, 22 Feb 2026 22:19:18 -0500 Subject: [PATCH] feat: add auth fields to ServerInfo and ClientOptions protocol types --- src/NATS.Server/Protocol/NatsProtocol.cs | 27 ++++++++++ tests/NATS.Server.Tests/AuthProtocolTests.cs | 56 ++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 tests/NATS.Server.Tests/AuthProtocolTests.cs diff --git a/src/NATS.Server/Protocol/NatsProtocol.cs b/src/NATS.Server/Protocol/NatsProtocol.cs index 75ccde0..fbfa1bb 100644 --- a/src/NATS.Server/Protocol/NatsProtocol.cs +++ b/src/NATS.Server/Protocol/NatsProtocol.cs @@ -26,6 +26,10 @@ public static class NatsProtocol public const string ErrMaxPayloadViolation = "Maximum Payload Violation"; public const string ErrInvalidPublishSubject = "Invalid Publish Subject"; public const string ErrInvalidSubject = "Invalid Subject"; + public const string ErrAuthorizationViolation = "Authorization Violation"; + public const string ErrAuthTimeout = "Authentication Timeout"; + public const string ErrPermissionsPublish = "Permissions Violation for Publish"; + public const string ErrPermissionsSubscribe = "Permissions Violation for Subscription"; } public sealed class ServerInfo @@ -61,6 +65,14 @@ public sealed class ServerInfo [JsonPropertyName("client_ip")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string? ClientIp { get; set; } + + [JsonPropertyName("auth_required")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] + public bool AuthRequired { get; set; } + + [JsonPropertyName("nonce")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? Nonce { get; set; } } public sealed class ClientOptions @@ -91,4 +103,19 @@ public sealed class ClientOptions [JsonPropertyName("no_responders")] public bool NoResponders { get; set; } + + [JsonPropertyName("user")] + public string? Username { get; set; } + + [JsonPropertyName("pass")] + public string? Password { get; set; } + + [JsonPropertyName("auth_token")] + public string? Token { get; set; } + + [JsonPropertyName("nkey")] + public string? Nkey { get; set; } + + [JsonPropertyName("sig")] + public string? Sig { get; set; } } diff --git a/tests/NATS.Server.Tests/AuthProtocolTests.cs b/tests/NATS.Server.Tests/AuthProtocolTests.cs new file mode 100644 index 0000000..4286616 --- /dev/null +++ b/tests/NATS.Server.Tests/AuthProtocolTests.cs @@ -0,0 +1,56 @@ +using System.Text.Json; +using NATS.Server.Protocol; + +namespace NATS.Server.Tests; + +public class AuthProtocolTests +{ + [Fact] + public void ClientOptions_deserializes_auth_fields() + { + var json = """{"user":"alice","pass":"secret","auth_token":"mytoken","nkey":"UABC","sig":"base64sig"}"""; + var opts = JsonSerializer.Deserialize(json); + + opts.ShouldNotBeNull(); + opts.Username.ShouldBe("alice"); + opts.Password.ShouldBe("secret"); + opts.Token.ShouldBe("mytoken"); + opts.Nkey.ShouldBe("UABC"); + opts.Sig.ShouldBe("base64sig"); + } + + [Fact] + public void ServerInfo_serializes_auth_required_and_nonce() + { + var info = new ServerInfo + { + ServerId = "test", + ServerName = "test", + Version = "0.1.0", + Host = "127.0.0.1", + Port = 4222, + AuthRequired = true, + Nonce = "abc123", + }; + + var json = JsonSerializer.Serialize(info); + json.ShouldContain("\"auth_required\":true"); + json.ShouldContain("\"nonce\":\"abc123\""); + } + + [Fact] + public void ServerInfo_omits_nonce_when_null() + { + var info = new ServerInfo + { + ServerId = "test", + ServerName = "test", + Version = "0.1.0", + Host = "127.0.0.1", + Port = 4222, + }; + + var json = JsonSerializer.Serialize(info); + json.ShouldNotContain("nonce"); + } +}