Documentation Index
Fetch the complete documentation index at: https://mintlify.com/nats-io/nats-server/llms.txt
Use this file to discover all available pages before exploring further.
Authorization Overview
NATS Server authorization controls what authenticated users can publish and subscribe to. Permissions are granted at the subject level, providing fine-grained access control.
Permissions System
The permission system operates on two dimensions:
- Publish Permissions - Control which subjects a user can publish messages to
- Subscribe Permissions - Control which subjects a user can subscribe to
Each permission dimension supports:
- Allow rules - Explicitly permit access to subjects
- Deny rules - Explicitly prohibit access to subjects (override allow rules)
Basic Permission Structure
permissions {
publish {
allow: ["subject1", "subject2.>"]
deny: ["subject2.admin"]
}
subscribe {
allow: ["results.>", "_INBOX.>"]
deny: ["results.internal.>"]
}
}
Subject Permission Rules
Wildcards
NATS supports two wildcard types:
* - Matches a single token
> - Matches one or more tokens (must be last)
Examples:
permissions {
publish {
allow: [
"events.*", # events.login, events.logout
"logs.app.>" # logs.app.error, logs.app.info.user
]
}
}
Deny Override
Deny rules always override allow rules:
permissions {
publish {
allow: ["data.>"]
deny: ["data.sensitive.>"]
}
}
This user can publish to data.public but NOT data.sensitive.passwords.
User-Level Permissions
Username/Password Users
authorization {
users = [
{
user: "publisher"
password: "$2a$11$..."
permissions: {
publish: ["events.>"]
subscribe: [] # Cannot subscribe
}
}
{
user: "subscriber"
password: "$2a$11$..."
permissions: {
publish: ["_INBOX.>"]
subscribe: ["events.>"]
}
}
]
}
NKey Users
authorization {
users = [
{
nkey: "UCKASD5KPQQYHB6KYD7RC62VZQN7VRU5NN2BKL7UFBQ3UBYAJQPVNHSQ"
permissions: {
publish: {
allow: ["orders.>"]
deny: ["orders.cancel"]
}
subscribe: {
allow: ["results.>", "_INBOX.>"]
}
}
}
]
}
Account-Based Authorization
Accounts provide complete isolation between groups of users.
Multi-Account Configuration
accounts {
PROD: {
users: [
{
user: "prod_user"
password: "$2a$11$..."
permissions: {
publish: ["production.>"]
subscribe: ["production.>"]
}
}
]
}
DEV: {
users: [
{
user: "dev_user"
password: "$2a$11$..."
permissions: {
publish: ["dev.>"]
subscribe: ["dev.>"]
}
}
]
}
}
Users in different accounts cannot communicate unless explicit account imports/exports are configured.
Account Isolation
Accounts provide:
- Subject namespace isolation -
production.orders in PROD is separate from production.orders in DEV
- Resource isolation - Connection and subscription limits per account
- Security boundaries - Complete separation between tenants
Response Permissions
Allow clients to respond to request-reply messages dynamically:
authorization {
users = [
{
user: "service"
password: "$2a$11$..."
permissions: {
publish: {}
subscribe: ["requests.>"]
responses: {
max: 100 # Max responses allowed
ttl: "10s" # Response permission expires after 10s
}
}
}
]
}
Response Permission Behavior
- User subscribes to
requests.service
- Request arrives with reply subject
_INBOX.abc123
- User granted temporary publish permission to
_INBOX.abc123
- Permission expires after TTL or max messages reached
Default Response Limits
From source code (server/auth.go:256-261):
DEFAULT_ALLOW_RESPONSE_MAX_MSGS = 1
DEFAULT_ALLOW_RESPONSE_EXPIRATION = 2 * time.Minute
Permission Examples
Read-Only Consumer
{
user: "consumer"
password: "$2a$11$..."
permissions: {
publish: ["_INBOX.>"] # Only reply subjects
subscribe: ["events.>", "data.>"]
}
}
Publisher-Only
{
user: "publisher"
password: "$2a$11$..."
permissions: {
publish: ["events.app.>"]
subscribe: [] # No subscriptions allowed
}
}
Request-Reply Service
{
user: "api_service"
password: "$2a$11$..."
permissions: {
subscribe: ["api.requests.>"]
responses: {
max: 1
ttl: "30s"
}
}
}
Admin User
{
user: "admin"
password: "$2a$11$..."
permissions: {
publish: {
allow: [">"]
deny: ["$SYS.>"]
}
subscribe: {
allow: [">"]
deny: ["$SYS.>"]
}
}
}
Service-Specific Permissions
{
user: "order_service"
password: "$2a$11$..."
permissions: {
publish: {
allow: [
"orders.created",
"orders.updated",
"orders.cancelled"
]
}
subscribe: {
allow: [
"orders.commands.>",
"_INBOX.>"
]
}
}
}
Connection Type Restrictions
Restrict users to specific connection types:
authorization {
users = [
{
user: "mqtt_only"
password: "$2a$11$..."
allowed_connection_types: ["MQTT"]
permissions: {
publish: ["sensors.>"]
subscribe: ["commands.>"]
}
}
]
}
Supported connection types:
STANDARD - Regular NATS clients
WEBSOCKET - WebSocket clients
LEAFNODE - Leaf node connections
MQTT - MQTT clients
Route Permissions
Control what subjects can be imported/exported between servers in a cluster:
cluster {
name: "production"
permissions: {
import: {
allow: ["public.>"]
deny: ["public.internal.>"]
}
export: {
allow: ["public.>"]
deny: ["public.internal.>"]
}
}
}
Account Imports and Exports
Accounts can selectively share subjects:
Export from Account
accounts {
SERVICE: {
exports: [
{stream: "service.api.>"} # Public API
{service: "service.request.>"} # Request-reply service
]
}
}
Import into Account
accounts {
CLIENT: {
imports: [
{stream: {account: "SERVICE", subject: "service.api.>"}, prefix: "external.service"}
{service: {account: "SERVICE", subject: "service.request.>"}, to: "service.req"}
]
}
}
Permission Validation
From server/auth.go implementation:
Publish Check
- Check deny list first - if matched, reject
- If allow list empty, default permit
- If allow list exists, subject must match
Subscribe Check
- Check deny list first - if matched, reject
- If allow list empty, default permit
- If allow list exists, subject must match
Testing Permissions
Test permissions before deploying:
# Test publish permission
nats-cli pub test.subject "hello" --creds=user.creds
# Test subscribe permission
nats-cli sub test.subject --creds=user.creds
Best Practices
1. Principle of Least Privilege
Grant minimal required permissions:
# Good - Specific permissions
permissions: {
publish: ["metrics.service1.>"]
subscribe: ["config.service1.>"]
}
# Bad - Overly permissive
permissions: {
publish: [">"]
subscribe: [">"]
}
2. Use Deny Rules for Exceptions
permissions: {
publish: {
allow: ["logs.>"]
deny: ["logs.sensitive.>"]
}
}
3. Organize by Account
Separate environments and tenants:
accounts {
PROD: { ... }
STAGING: { ... }
DEV: { ... }
}
4. Enable Response Permissions
For request-reply patterns:
responses: {
max: 1
ttl: "5s"
}