feat: enforce jwt allowed connection types with go-compatible semantics
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
using System.Security.Cryptography.X509Certificates;
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
using NATS.Server.Auth.Jwt;
|
||||||
using NATS.Server.Protocol;
|
using NATS.Server.Protocol;
|
||||||
|
|
||||||
namespace NATS.Server.Auth;
|
namespace NATS.Server.Auth;
|
||||||
@@ -19,5 +20,5 @@ public sealed class ClientAuthContext
|
|||||||
/// Used by JWT authenticator to enforce allowed_connection_types claims.
|
/// Used by JWT authenticator to enforce allowed_connection_types claims.
|
||||||
/// Defaults to "STANDARD" for regular NATS client connections.
|
/// Defaults to "STANDARD" for regular NATS client connections.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string ConnectionType { get; init; } = "STANDARD";
|
public string ConnectionType { get; init; } = JwtConnectionTypes.Standard;
|
||||||
}
|
}
|
||||||
|
|||||||
34
src/NATS.Server/Auth/Jwt/JwtConnectionTypes.cs
Normal file
34
src/NATS.Server/Auth/Jwt/JwtConnectionTypes.cs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
namespace NATS.Server.Auth.Jwt;
|
||||||
|
|
||||||
|
internal static class JwtConnectionTypes
|
||||||
|
{
|
||||||
|
public const string Standard = "STANDARD";
|
||||||
|
public const string Websocket = "WEBSOCKET";
|
||||||
|
public const string Leafnode = "LEAFNODE";
|
||||||
|
public const string LeafnodeWs = "LEAFNODE_WS";
|
||||||
|
public const string Mqtt = "MQTT";
|
||||||
|
public const string MqttWs = "MQTT_WS";
|
||||||
|
public const string InProcess = "INPROCESS";
|
||||||
|
|
||||||
|
private static readonly HashSet<string> Known =
|
||||||
|
[
|
||||||
|
Standard, Websocket, Leafnode, LeafnodeWs, Mqtt, MqttWs, InProcess,
|
||||||
|
];
|
||||||
|
|
||||||
|
public static (HashSet<string> Valid, bool HasUnknown) Convert(IEnumerable<string>? values)
|
||||||
|
{
|
||||||
|
var valid = new HashSet<string>(StringComparer.Ordinal);
|
||||||
|
var hasUnknown = false;
|
||||||
|
if (values is null) return (valid, false);
|
||||||
|
|
||||||
|
foreach (var raw in values)
|
||||||
|
{
|
||||||
|
var up = (raw ?? string.Empty).Trim().ToUpperInvariant();
|
||||||
|
if (up.Length == 0) continue;
|
||||||
|
if (Known.Contains(up)) valid.Add(up);
|
||||||
|
else hasUnknown = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (valid, hasUnknown);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -95,6 +95,24 @@ public sealed class JwtAuthenticator : IAuthenticator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 7b. Check allowed connection types
|
||||||
|
var (allowedTypes, hasUnknown) = JwtConnectionTypes.Convert(userClaims.Nats?.AllowedConnectionTypes);
|
||||||
|
|
||||||
|
if (allowedTypes.Count == 0)
|
||||||
|
{
|
||||||
|
if (hasUnknown)
|
||||||
|
return null; // unknown-only list should reject
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var connType = string.IsNullOrWhiteSpace(context.ConnectionType)
|
||||||
|
? JwtConnectionTypes.Standard
|
||||||
|
: context.ConnectionType.ToUpperInvariant();
|
||||||
|
|
||||||
|
if (!allowedTypes.Contains(connType))
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// 8. Build permissions from JWT claims
|
// 8. Build permissions from JWT claims
|
||||||
Permissions? permissions = null;
|
Permissions? permissions = null;
|
||||||
var nats = userClaims.Nats;
|
var nats = userClaims.Nats;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using System.Text.Json;
|
|||||||
using System.Threading.Channels;
|
using System.Threading.Channels;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using NATS.Server.Auth;
|
using NATS.Server.Auth;
|
||||||
|
using NATS.Server.Auth.Jwt;
|
||||||
using NATS.Server.Protocol;
|
using NATS.Server.Protocol;
|
||||||
using NATS.Server.Subscriptions;
|
using NATS.Server.Subscriptions;
|
||||||
using NATS.Server.Tls;
|
using NATS.Server.Tls;
|
||||||
@@ -388,6 +389,7 @@ public sealed class NatsClient : IDisposable
|
|||||||
Opts = ClientOpts,
|
Opts = ClientOpts,
|
||||||
Nonce = _nonce ?? [],
|
Nonce = _nonce ?? [],
|
||||||
ClientCertificate = TlsState?.PeerCert,
|
ClientCertificate = TlsState?.PeerCert,
|
||||||
|
ConnectionType = JwtConnectionTypes.Standard,
|
||||||
};
|
};
|
||||||
|
|
||||||
authResult = _authService.Authenticate(context);
|
authResult = _authService.Authenticate(context);
|
||||||
|
|||||||
Reference in New Issue
Block a user