Checks/USER_001

NATS Bearer Token User: What It Means and How to Fix It

Severity
Warning
Category
Errors
Applies to
User
Check ID
USER_001
Detection threshold
bearer token user has active connections

A bearer token user is a NATS user whose authentication skips nonce signature verification during the CONNECT handshake, relying on JWT validity alone rather than cryptographic challenge-response proof. Unlike NKey-based authentication where the client signs a server-issued nonce with its private key, bearer tokens bypass this step entirely. If an attacker obtains the token — over the network, from a config file, or from a log — they can impersonate the user with no additional proof of identity. This check flags bearer token users with active connections, indicating the weaker authentication method is actively in use.

Why this matters

Bearer tokens are the weakest form of NATS authentication. Unlike NKey authentication, where the server sends a cryptographic challenge and the client proves it holds the private key without ever transmitting it, bearer tokens work by sending the secret itself over the wire. If the connection isn’t encrypted with TLS, the token is visible to anyone who can observe the network traffic. Even with TLS, a static token is a single point of compromise — anyone who obtains the token from any source (config files, environment variables, CI/CD logs, source code) can connect as that user indefinitely.

The security implications compound in multi-tenant environments. A bearer token doesn’t distinguish between individual clients — every connection using the same token looks identical to the server. There’s no per-client identity, no audit trail distinguishing which specific process or deployment connected, and no way to revoke access for a single client without rotating the token for all clients that share it.

Bearer tokens also lack expiration by default. An NKey-based JWT credential can have a built-in expiry time and be revoked centrally. A bearer token remains valid until someone manually changes it in the server configuration and reloads — a process that requires coordinated updates across every client that uses the token.

Common causes

  • Legacy configuration from initial deployment. Token auth is the simplest to set up — one line in the server config, one flag on the client. Many deployments start with token auth during development or proof-of-concept and never migrate to stronger methods before reaching production.

  • Shared credentials across environments. A single token is used in dev, staging, and production because it’s “easier.” The token leaks into CI/CD logs, developer machines, and container images, expanding the attack surface with every copy.

  • Lack of awareness of NKey/JWT authentication. Teams unfamiliar with NATS security may not know that challenge-response authentication exists and is straightforward to configure. Token auth appears adequate if you’re not thinking about interception or credential rotation.

  • Automated provisioning without auth integration. Infrastructure-as-code scripts or Helm charts that deploy NATS use token auth because integrating NKey generation into the provisioning pipeline wasn’t prioritized.

  • Third-party integrations requiring simple credentials. Some systems that connect to NATS only support basic token or username/password authentication, forcing the use of weaker auth methods for those specific connections.

How to diagnose

Identify bearer token configuration

Bearer token auth is configured in the server config file. Look for the authorization block with a token field:

1
# Server config — bearer token auth
2
authorization {
3
token: "s3cret-token-value"
4
}

Or per-user token configuration:

1
authorization {
2
users = [
3
{ user: "app1", password: "s3cret" }
4
]
5
}

Check if authentication is enforced

Terminal window
nats server info

Verify that auth_required is true. If authentication isn’t required at all (SERVER_007), that’s an even more critical issue.

Identify active connections using token auth

Query the server’s connection details:

Terminal window
curl -s http://localhost:8222/connz?auth=true&limit=100 | \
jq '.connections[] | {cid, name, ip, authorized_user, lang, version}'

Connections using bearer token auth will show the authorized user associated with the token. Cross-reference with the server configuration to determine which users are token-based versus NKey-based.

Audit TLS status on token-authenticated connections

If bearer tokens must remain temporarily, ensure all connections using them are TLS-encrypted:

Terminal window
curl -s http://localhost:8222/connz?auth=true&limit=100 | \
jq '.connections[] | select(.tls_version == null) | {cid, name, ip, authorized_user}'

Any result here is a bearer token transmitted in cleartext — the highest-risk scenario.

How to fix it

Immediate: enforce TLS on all connections

If migration away from bearer tokens will take time, the first step is ensuring tokens are at least encrypted in transit:

1
# Server config — require TLS
2
tls {
3
cert_file: "/path/to/server-cert.pem"
4
key_file: "/path/to/server-key.pem"
5
ca_file: "/path/to/ca.pem"
6
}
Terminal window
# Reload server config without restart
nats-server --signal reload

This doesn’t fix the fundamental weakness of bearer tokens, but it eliminates the network interception vector.

Short-term: migrate to NKey authentication

NKey authentication uses Ed25519 key pairs. The server sends a random challenge (nonce), the client signs it with its private key, and the server verifies the signature against the known public key. The private key never leaves the client.

Generate an NKey pair:

Terminal window
# nk is the dedicated NKey CLI (https://github.com/nats-io/nkeys)
nk -gen user -pubout

This outputs an NKey seed (private key) and the corresponding public key. (nats server passwd only generates bcrypt password hashes — it has no NKey mode. For decentralized auth deployments, prefer nsc add user, which generates the NKey and JWT in one step.)

Update the server configuration:

1
authorization {
2
users = [
3
{ nkey: "UABJHNYH2PQE3EAAV5Y6YEUDMZTLNFZPWAJDRB5QMHBZQOSMG6BQRPE" }
4
]
5
}

Update the client connection:

1
// Go — connect with NKey
2
opt, _ := nats.NkeyOptionFromSeed("/path/to/user.nk")
3
nc, err := nats.Connect(url, opt)
1
# Python (nats.py) — connect with NKey
2
import nats
3
import os
4
5
async def main():
6
nc = await nats.connect(
7
servers=["nats://localhost:4222"],
8
nkey="/path/to/user.nk",
9
)

Long-term: adopt decentralized JWT authentication

For multi-tenant or larger deployments, JWT-based auth with NKey signing provides the most complete security model:

  • Per-user identity with unique credentials per client
  • Centralized revocation without server config changes
  • Expiration built into the credential
  • Account isolation with explicit import/export between tenants
Terminal window
# Create an operator, account, and user with the nsc tool
nsc add operator --generate-signing-key --sys --name MyOperator
nsc add account --name Production
nsc add user --name order-processor --account Production
1
// Go — connect with user credentials (JWT + NKey)
2
nc, err := nats.Connect(url,
3
nats.UserCredentials("/path/to/user.creds"),
4
)

Synadia Insights flags bearer token users with active connections automatically, giving security teams visibility into which authentication methods are actively in use across the deployment — no manual config auditing required.

Frequently asked questions

Is bearer token authentication ever acceptable?

Bearer tokens are appropriate for WebSocket and HTTP contexts where NKey signing is impractical — browser-based clients and simple HTTP integrations often can’t perform Ed25519 signing in the CONNECT handshake. In these cases, bearer tokens are a reasonable trade-off. However, they should not be used for long-lived server-to-server connections where NKey authentication is straightforward to implement. In isolated development environments with no sensitive data, token auth is also low-risk and convenient. In all cases, enforce TLS, restrict the token to a limited-permission account, and set a deadline for migration where possible.

What’s the difference between bearer token auth and username/password auth?

Functionally, they’re similar — both send a secret over the wire during connection. Username/password auth allows multiple distinct users with different permissions, while a single bearer token gives the same identity to every client that uses it. Neither provides challenge-response security. For password-based auth, the server supports bcrypt hashing (generated via nats server passwd) which at least protects the credential at rest in the config file, but the password is still sent in cleartext during the CONNECT handshake unless TLS is enabled.

How do I rotate a bearer token without downtime?

NATS doesn’t support multiple concurrent valid tokens natively. The typical approach: update the server config with the new token, reload the config, then update all clients to use the new token. Clients with the old token will fail to authenticate on their next reconnect. To avoid a flash of disconnections, coordinate the rollout: update clients first (they’ll continue using the old token on existing connections), then reload the server. New connections will require the new token, and existing connections remain valid until they reconnect. For zero-downtime rotation, NKey or JWT-based auth is strongly preferred — JWT credentials can be issued with expiration and revoked centrally.

Does this check fire for username/password users too?

This check specifically flags bearer token users — those configured with the token field in the authorization block. Username/password users are a separate configuration pattern. Both are weaker than NKey authentication, but bearer tokens are flagged because they represent the lowest level of identity assurance: a single shared secret with no per-user distinction.

How do I migrate a large deployment from tokens to NKeys?

Start with a phased approach: generate NKey pairs for each service, update the server config to accept both the old token and NKey users during the transition (list both in the users array), then migrate clients one service at a time. Once all clients are using NKeys, remove the token entry and reload. The nsc tool can automate NKey generation and credential distribution for large deployments. Plan for a transition window where both auth methods are accepted simultaneously.

Proactive monitoring for NATS bearer token user with Synadia Insights

With 100+ always-on audit Checks from the NATS experts, Insights helps you find and fix problems before they become costly incidents.
No alert rules to write. No dashboards to maintain.

Start a 14-day Insights trial
Cancel