Skip to content

Instantly share code, notes, and snippets.

@aricart
Last active September 17, 2024 20:40
Show Gist options
  • Save aricart/0b3ab133d1926fa2bc8c81752f812cae to your computer and use it in GitHub Desktop.
Save aricart/0b3ab133d1926fa2bc8c81752f812cae to your computer and use it in GitHub Desktop.
delegated authentication macros

A small example showing delegated authentication (JWT) subject macros that reference values in the JWT. Note these macros are only valid in scoped signing keys (templates)

The macros are:

  • name() - the name field in the user JWT - note this shouldn't be used unless names are guaranteed to not have spaces.
  • subject() - the users public key (subject)
  • account-name() - the name field in the account account JWT - note this shouldn't be used unless names are guaranteed to not have spaces.
  • account-subject() the account public key
  • tag(name) - an user tag in the form name:value
  • account-tag(name) - an account tag in the form name:value
import { NatsServer } from "/Users/aricart/src/github.com/nats-io/nats.js/test_helpers/mod.ts";
import { connect } from "@nats-io/transport-deno";
import { NatsConnectionImpl } from "@nats-io/nats-core/internal";
import {
createAccount,
createOperator,
createUser,
defaultUserPermissionsLimits,
encodeAccount,
encodeOperator,
encodeUser,
newScopedSigner,
type UserPermissionsLimits,
} from "https://jsr.io/@nats-io/jwt/0.0.9-3/src/mod.ts";
import {
jwtAuthenticator,
} from "https://jsr.io/@nats-io/nats-core/3.0.0-1/mod.ts";
const O = createOperator();
const SYS = createAccount();
const A = createAccount();
const AA = createAccount();
const U = createUser();
const authenticator = jwtAuthenticator(
await encodeUser("U", U, A, {tags:["op:hello"]}, { signer: AA, scopedUser: true }),
);
const resolver: Record<string, string> = {};
resolver[A.getPublicKey()] = await encodeAccount("A", A, {
signing_keys: [
newScopedSigner(
AA,
"test",
defaultUserPermissionsLimits({
bearer_token: true,
sub: {
allow: [">"],
},
pub: {
allow: ["hi", "$SYS.>", "foo.{{subject()}}", "bar.{{account-tag(car)}}", "op.{{tag(op)}}"],
},
} as Partial<UserPermissionsLimits>),
),
],
tags: ["car:BMW"],
limits: {
conn: -1,
subs: -1,
},
}, { signer: O });
resolver[SYS.getPublicKey()] = await encodeAccount("SYS", SYS, {
limits: {
conn: -1,
subs: -1,
},
}, { signer: O });
const conf = {
debug: true,
operator: await encodeOperator("O", O, {
tags: ["op:smooth"],
system_account: SYS.getPublicKey(),
}),
resolver: "MEMORY",
"resolver_preload": resolver,
};
const ns = await NatsServer.start(conf, true);
const nc = await connect({
port: ns.port,
authenticator,
}) as NatsConnectionImpl;
console.log(await nc.context());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment