NATS Logo by Example

Auth Callout - Centralized in Authentication and Authorization

Auth callout is a new feature in NATS v2.10.0 providing an extension point for integrating with alternative identity and access management (IAM) backends. See the official docs for more details.

This example demonstrates how auth callout can be configured within server configuration. This is combined with a basic service that handles the authorization requests delegated by the NATS server.

CLI Go Python JavaScript Rust C# .NET V2 Java Ruby Elixir Crystal C
Jump to the output or the recording
$ nbe run auth/callout/cli
View the source code or learn how to run this example yourself

Code

#!/bin/bash


set -eou pipefail


NATS_URL="nats://localhost:4222"

Use a static issuer Nkey and Xkey for this example. Typically this would be generated using the nsc generate nkey --account and nsc generate nkey --curve commands, respectively, or programmatically with one of the nkeys libraries.

ISSUER_NKEY="ABJHLOVMPA4CI6R5KLNGOB4GSLNIY7IOUPAJC4YFNDLQVIOBYQGUWVLA"
ISSUER_NSEED="SAANDLKMXL6CUS3CP52WIXBEDN6YJ545GDKC65U5JZPPV6WH6ESWUA6YAI"


ISSUER_XKEY="XAB3NANV3M6N7AHSQP2U5FRWKKUT7EG2ZXXABV4XVXYQRJGM4S2CZGHT"
ISSUER_XSEED="SXAAXMRAEP6JWWHNB6IKFL554IE6LZVT6EY5MBRICPILTLOPHAG73I3YX4"

Create multi-account config with auth callout enabled and encryption.

cat <<- EOF > server.conf
accounts {
  AUTH {
    users: [
      { user: auth, password: auth }
    ]
  }
  APP {}
  SYS {}
}


authorization {
  auth_callout {
    issuer: $ISSUER_NKEY
    users: [ auth ]
    account: AUTH
    xkey: $ISSUER_XKEY
  }
}


system_account: SYS
EOF

Start the server.

nats-server -c server.conf > /dev/null 2>&1 &
sleep 1

Write out some users emulating a user directory backend.

cat <<- EOF > users.json
{
  "sys": {
    "pass": "sys",
    "account": "SYS"
  },
  "alice": {
    "pass": "alice",
    "account": "APP"
  },
  "bob": {
    "pass": "bob",
    "account": "APP",
    "permissions": {
      "pub": {
        "allow": ["bob.>"]
      },
      "sub": {
        "allow": ["bob.>"]
      },
      "resp": {
        "max": 1
      }
    }
  }
}
EOF

Start the auth callout service providing the auth credentials to connect and the issuer seed.

service \
  -nats.url $NATS_URL \
  -nats.user auth \
  -nats.pass auth \
  -issuer.seed $ISSUER_NSEED \
  -xkey.seed $ISSUER_XSEED \
  -users users.json &


sleep 1

Confirm alice can connect and publish.

echo 'Test alice'
nats --user alice --password alice pub test 'hello from alice'

Confirm bob cannot publish to a subject they are not allowed to.

echo 'Test bob on denied subject'
nats --user bob --password bob pub test 'hello from bob' || true

Confirm bob can connect and publish to a subject they are allowed to.

echo 'Test bob on allowed subject'
nats --user bob --password bob pub bob.test 'hello from bob'

Confirm an unknown user cannot connect.

echo 'Test unknown user'
nats --user pam --password pam pub test 'hello from pam' || true

Confirm the system account user has the expected system permission.

echo 'Test system account user'
nats --user sys --password sys server list

Output

Test alice
19:30:25 Published 16 bytes to "test"
Test bob on denied subject
19:30:25 Unexpected NATS error: nats: Permissions Violation for Publish to "test"
nats: error: nats: Permissions Violation for Publish to "test"
Test bob on allowed subject
19:30:25 Published 14 bytes to "bob.test"
Test unknown user
nats: error: nats: Authorization Violation
Test system account user
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│                                                                            Server Overview                                                                            │
├──────────────────────────────────────────────────────────┬─────────┬──────┬─────────┬────┬───────┬──────┬────────┬─────┬────────┬───────┬───────┬──────┬────────┬─────┤
│ Name                                                     │ Cluster │ Host │ Version │ JS │ Conns │ Subs │ Routes │ GWs │ Mem    │ CPU % │ Cores │ Slow │ Uptime │ RTT │
├──────────────────────────────────────────────────────────┼─────────┼──────┼─────────┼────┼───────┼──────┼────────┼─────┼────────┼───────┼───────┼──────┼────────┼─────┤
│ NATGJ6PRBRYSRRFA6UXDHXNM4Q72YKQZOF4IJP2UWX52QKXIOHB2KSRV │         │ 0    │ 2.10.1  │ no │ 2     │ 73   │      0 │   0 │ 11 MiB │ 0     │     8 │    0 │ 2.34s  │ 6ms │
├──────────────────────────────────────────────────────────┼─────────┼──────┼─────────┼────┼───────┼──────┼────────┼─────┼────────┼───────┼───────┼──────┼────────┼─────┤
│                                                          │ 0       │ 1    │         │ 0  │ 2     │ 73   │        │     │ 11 MIB │       │       │    0 │        │     │
╰──────────────────────────────────────────────────────────┴─────────┴──────┴─────────┴────┴───────┴──────┴────────┴─────┴────────┴───────┴───────┴──────┴────────┴─────╯

Recording

Note, playback is half speed to make it a bit easier to follow.