Created
July 31, 2022 19:55
-
-
Save theBoEffect/ccdfe18cff5ec7876c784a3c7a45d307 to your computer and use it in GitHub Desktop.
Programmatically Creating an Account and User in NATS.io Using Node
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// using require rather than import to make this simple for a standard javascript example | |
const {connect, StringCodec, credsAuthenticator} = require('nats'); | |
const {encodeAccount, encodeUser} = require('nats-jwt'); | |
const {createAccount, createUser, fromSeed} = require('nkeys.js'); | |
// The Seed representing the Operator - you'll need this to sign new Accounts. Notice it starts with 'SO' | |
const opSeed = 'SOA...'; | |
// The JWT representing the User from the System Account (Step 4) | |
const sysJwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJlZDI1NTE5LW5rZXkifQ...'; | |
// The Seed representing the User from the System Account (Step 3). Notice it starts with 'SU' | |
const sysSeed = 'SUA...'; | |
// A function to define the contents of a credentials file. Needed for a client to authenticate | |
function returnCreds(jwt, seed) { | |
return `-----BEGIN NATS USER JWT----- | |
${jwt} | |
------END NATS USER JWT------ | |
************************* IMPORTANT ************************* | |
NKEY Seed printed below can be used sign and prove identity. | |
NKEYs are sensitive and should be treated as secrets. | |
-----BEGIN USER NKEY SEED----- | |
${seed} | |
------END USER NKEY SEED------ | |
`; | |
} | |
(async () => { | |
// Lets generate an Operator object 'opk' | |
const operator = fromSeed(new TextEncoder().encode(opSeed)); | |
// Lets generate a NEW account | |
const account = createAccount(); | |
console.info(`Account Public Key - ${account.getPublicKey()}`); | |
console.info(`Account Private Key - ${new TextDecoder().decode(account.getPrivateKey())}`); | |
console.info(`Account Seed Key - ${new TextDecoder().decode(account.getSeed())}`); | |
// Lets generate a NEW User | |
const user = createUser(); | |
console.info(`User Public Key - ${user.getPublicKey()}`); | |
console.info(`User Private Key - ${new TextDecoder().decode(user.getPrivateKey())}`); | |
console.info(`User Seed Key - ${new TextDecoder().decode(user.getSeed())}`); | |
const userSeed = new TextDecoder().decode(user.getSeed()); | |
// Lets generate a JWT for the Account and sign that JWT with the operator - this will result in the JWT iss claim being the operator public key | |
// first we define the limits of the account and also enable JetStream by defining mem_storage and disk_storage | |
const nats = { | |
"limits": { | |
"subs": -1, | |
"data": -1, | |
"payload": -1, | |
"imports": -1, | |
"exports": -1, | |
"wildcards": true, | |
"conn": -1, | |
"leaf": -1, | |
"mem_storage": -1, | |
"disk_storage": -1 | |
} | |
} | |
const accJwt = await encodeAccount('my-account', account, nats, { signer: operator } ); | |
console.info(`ACCOUNT JWT - ${accJwt}`); | |
// Lets generate a JWT for the User and sign it with the Account | |
const config = { | |
"pub": {}, | |
"sub": {}, | |
"subs": -1, | |
"data": -1, | |
"payload": -1, | |
"issuer_account": account.getPublicKey() | |
} | |
const userJwt = await encodeUser('my-user', user, account, config) | |
console.info(`USER JWT - ${userJwt}`); | |
// Lets push the new Account to NATS | |
// First we create a system account credentials record | |
const sysCreds = returnCreds(sysJwt, sysSeed); | |
// Then we use this system credentials record to connect to NATS with our node client | |
const nc = await connect({ servers: "localhost:4222", authenticator: credsAuthenticator(new TextEncoder().encode(sysCreds)) }); | |
// create a codec | |
const sc = StringCodec(); | |
// Publish the new account to the $SYS.REQ.CLAIMS.UPDATE subject to save it to the /local/jwt folder | |
try { | |
const m = await nc.request("$SYS.REQ.CLAIMS.UPDATE", sc.encode(accJwt)); | |
console.log(`got response: ${sc.decode(m.data)}`); | |
} catch (err) { | |
console.log(`problem with request: ${err.message}`); | |
console.info(err); | |
} | |
await nc.close(); | |
// FINALLY, lets use our new User JWT to subscribe to a topic of our choosing. | |
// If we've done this correctly, this user will be authenticated and authorized | |
const userCreds = returnCreds(userJwt, userSeed); | |
const nc2 = await connect({ servers: "localhost:4222", authenticator: credsAuthenticator(new TextEncoder().encode(userCreds)) }); | |
// create a simple subscriber and iterate over messages | |
// matching the subscription | |
const sub = nc2.subscribe("hello"); | |
(async () => { | |
for await (const m of sub) { | |
console.log(`[${sub.getProcessed()}]: ${sc.decode(m.data)}`); | |
} | |
console.log("subscription closed"); | |
})(); | |
await nc2.close(); | |
})() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment