417 lines
15 KiB
JavaScript
417 lines
15 KiB
JavaScript
/*
|
|
* Copyright 2018-2023 The NATS Authors
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
const test = require("ava");
|
|
const {
|
|
connect,
|
|
ErrorCode,
|
|
jwtAuthenticator,
|
|
nkeyAuthenticator,
|
|
credsAuthenticator,
|
|
StringCodec,
|
|
deferred,
|
|
} = require(
|
|
"./index",
|
|
);
|
|
const { nkeys, Events } = require("../lib/nats-base-client/internal_mod");
|
|
const { NatsServer, wsConfig } = require("./helpers/launcher");
|
|
const {
|
|
createOperator,
|
|
createAccount,
|
|
encodeAccount,
|
|
encodeOperator,
|
|
encodeUser,
|
|
createUser,
|
|
} = require("nats-jwt");
|
|
|
|
const conf = Object.assign({
|
|
authorization: {
|
|
PERM: {
|
|
subscribe: "bar",
|
|
publish: "foo",
|
|
},
|
|
users: [{
|
|
user: "derek",
|
|
password: "foobar",
|
|
permission: "$PERM",
|
|
}],
|
|
},
|
|
}, wsConfig());
|
|
|
|
test("auth - none", async (t) => {
|
|
t.plan(1);
|
|
const ns = await NatsServer.start(conf);
|
|
try {
|
|
const nc = await connect({ servers: `ws://127.0.0.1:${ns.websocket}` });
|
|
await nc.close();
|
|
t.fail("shouldnt have been able to connect");
|
|
} catch (ex) {
|
|
t.is(ex.code, ErrorCode.AuthorizationViolation);
|
|
}
|
|
await ns.stop();
|
|
});
|
|
|
|
test("auth - bad", async (t) => {
|
|
t.plan(1);
|
|
const ns = await NatsServer.start(conf);
|
|
try {
|
|
const nc = await connect(
|
|
{ servers: `ws://127.0.0.1:${ns.websocket}`, user: "me", pass: "hello" },
|
|
);
|
|
await nc.close();
|
|
t.fail("shouldnt have been able to connect");
|
|
} catch (ex) {
|
|
t.is(ex.code, ErrorCode.AuthorizationViolation);
|
|
}
|
|
await ns.stop();
|
|
});
|
|
|
|
test("auth - un/pw", async (t) => {
|
|
t.plan(1);
|
|
const ns = await NatsServer.start(conf);
|
|
const nc = await connect(
|
|
{
|
|
servers: `ws://127.0.0.1:${ns.websocket}`,
|
|
user: "derek",
|
|
pass: "foobar",
|
|
},
|
|
);
|
|
await nc.flush();
|
|
await nc.close();
|
|
await ns.stop();
|
|
t.pass();
|
|
});
|
|
|
|
test("auth - sub permissions", async (t) => {
|
|
t.plan(4);
|
|
const ns = await NatsServer.start(conf);
|
|
const nc = await connect(
|
|
{
|
|
servers: `ws://127.0.0.1:${ns.websocket}`,
|
|
user: "derek",
|
|
pass: "foobar",
|
|
},
|
|
);
|
|
|
|
const errStatus = deferred();
|
|
const _ = (async () => {
|
|
for await (const s of nc.status()) {
|
|
errStatus.resolve(s);
|
|
}
|
|
})();
|
|
|
|
const iterErr = deferred();
|
|
const sub = nc.subscribe("foo");
|
|
(async () => {
|
|
for await (const m of sub) {
|
|
}
|
|
})().catch((err) => {
|
|
iterErr.resolve(err);
|
|
});
|
|
|
|
const v = await Promise.all([errStatus, iterErr, sub.closed]);
|
|
t.is(v[0].data, ErrorCode.PermissionsViolation);
|
|
t.is(v[1].message, "'Permissions Violation for Subscription to \"foo\"'");
|
|
t.true(sub.isClosed());
|
|
t.false(nc.isClosed());
|
|
|
|
await nc.close();
|
|
await ns.stop();
|
|
});
|
|
|
|
test("auth - weird characters", async (t) => {
|
|
const pass = "§12§12§12";
|
|
const conf = Object.assign({
|
|
authorization: {
|
|
username: "admin",
|
|
password: pass,
|
|
},
|
|
}, wsConfig());
|
|
const ns = await NatsServer.start(conf);
|
|
|
|
const nc = await connect({
|
|
servers: [`ws://127.0.0.1:${ns.websocket}`],
|
|
user: "admin",
|
|
pass: pass,
|
|
});
|
|
await nc.flush;
|
|
await nc.close();
|
|
await ns.stop();
|
|
t.pass();
|
|
});
|
|
|
|
test("auth - pub perm", async (t) => {
|
|
t.plan(2);
|
|
const ns = await NatsServer.start(conf);
|
|
const nc = await connect(
|
|
{
|
|
servers: `ws://127.0.0.1:${ns.websocket}`,
|
|
user: "derek",
|
|
pass: "foobar",
|
|
},
|
|
);
|
|
const errStatus = deferred();
|
|
const _ = (async () => {
|
|
for await (const s of nc.status()) {
|
|
errStatus.resolve(s);
|
|
}
|
|
})();
|
|
|
|
nc.publish("bar");
|
|
|
|
const v = await errStatus;
|
|
t.is(v.data, ErrorCode.PermissionsViolation);
|
|
t.false(nc.isClosed());
|
|
|
|
await nc.close();
|
|
await ns.stop();
|
|
});
|
|
|
|
test("auth - token", async (t) => {
|
|
const ns = await NatsServer.start(
|
|
Object.assign({ authorization: { token: "foo" } }, wsConfig()),
|
|
);
|
|
const nc = await connect(
|
|
{ servers: `ws://127.0.0.1:${ns.websocket}`, token: "foo" },
|
|
);
|
|
await nc.flush();
|
|
await nc.close();
|
|
await ns.stop();
|
|
t.pass();
|
|
});
|
|
|
|
test("auth - nkey", async (t) => {
|
|
t.plan(1);
|
|
const kp = nkeys.createUser();
|
|
const pk = kp.getPublicKey();
|
|
const seed = kp.getSeed();
|
|
const conf = Object.assign({
|
|
authorization: {
|
|
users: [
|
|
{ nkey: pk },
|
|
],
|
|
},
|
|
}, wsConfig());
|
|
const ns = await NatsServer.start(conf);
|
|
const nc = await connect(
|
|
{
|
|
servers: `ws://127.0.0.1:${ns.websocket}`,
|
|
authenticator: nkeyAuthenticator(seed),
|
|
},
|
|
);
|
|
await nc.flush();
|
|
await nc.close();
|
|
await ns.stop();
|
|
t.pass();
|
|
});
|
|
|
|
test("auth - creds", async (t) => {
|
|
const creds = `-----BEGIN NATS USER JWT-----
|
|
eyJ0eXAiOiJqd3QiLCJhbGciOiJlZDI1NTE5In0.eyJqdGkiOiJFU1VQS1NSNFhGR0pLN0FHUk5ZRjc0STVQNTZHMkFGWERYQ01CUUdHSklKUEVNUVhMSDJBIiwiaWF0IjoxNTQ0MjE3NzU3LCJpc3MiOiJBQ1pTV0JKNFNZSUxLN1FWREVMTzY0VlgzRUZXQjZDWENQTUVCVUtBMzZNSkpRUlBYR0VFUTJXSiIsInN1YiI6IlVBSDQyVUc2UFY1NTJQNVNXTFdUQlAzSDNTNUJIQVZDTzJJRUtFWFVBTkpYUjc1SjYzUlE1V002IiwidHlwZSI6InVzZXIiLCJuYXRzIjp7InB1YiI6e30sInN1YiI6e319fQ.kCR9Erm9zzux4G6M-V2bp7wKMKgnSNqMBACX05nwePRWQa37aO_yObbhcJWFGYjo1Ix-oepOkoyVLxOJeuD8Bw
|
|
------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-----
|
|
SUAIBDPBAUTWCWBKIO6XHQNINK5FWJW4OHLXC3HQ2KFE4PEJUA44CNHTC4
|
|
------END USER NKEY SEED------
|
|
`;
|
|
|
|
const conf = Object.assign({
|
|
operator:
|
|
"eyJ0eXAiOiJqd3QiLCJhbGciOiJlZDI1NTE5In0.eyJhdWQiOiJURVNUUyIsImV4cCI6MTg1OTEyMTI3NSwianRpIjoiWE5MWjZYWVBIVE1ESlFSTlFPSFVPSlFHV0NVN01JNVc1SlhDWk5YQllVS0VRVzY3STI1USIsImlhdCI6MTU0Mzc2MTI3NSwiaXNzIjoiT0NBVDMzTVRWVTJWVU9JTUdOR1VOWEo2NkFIMlJMU0RBRjNNVUJDWUFZNVFNSUw2NU5RTTZYUUciLCJuYW1lIjoiU3luYWRpYSBDb21tdW5pY2F0aW9ucyBJbmMuIiwibmJmIjoxNTQzNzYxMjc1LCJzdWIiOiJPQ0FUMzNNVFZVMlZVT0lNR05HVU5YSjY2QUgyUkxTREFGM01VQkNZQVk1UU1JTDY1TlFNNlhRRyIsInR5cGUiOiJvcGVyYXRvciIsIm5hdHMiOnsic2lnbmluZ19rZXlzIjpbIk9EU0tSN01ZRlFaNU1NQUo2RlBNRUVUQ1RFM1JJSE9GTFRZUEpSTUFWVk40T0xWMllZQU1IQ0FDIiwiT0RTS0FDU1JCV1A1MzdEWkRSVko2NTdKT0lHT1BPUTZLRzdUNEhONk9LNEY2SUVDR1hEQUhOUDIiLCJPRFNLSTM2TFpCNDRPWTVJVkNSNlA1MkZaSlpZTVlXWlZXTlVEVExFWjVUSzJQTjNPRU1SVEFCUiJdfX0.hyfz6E39BMUh0GLzovFfk3wT4OfualftjdJ_eYkLfPvu5tZubYQ_Pn9oFYGCV_6yKy3KMGhWGUCyCdHaPhalBw",
|
|
resolver: "MEMORY",
|
|
resolver_preload: {
|
|
ACZSWBJ4SYILK7QVDELO64VX3EFWB6CXCPMEBUKA36MJJQRPXGEEQ2WJ:
|
|
"eyJ0eXAiOiJqd3QiLCJhbGciOiJlZDI1NTE5In0.eyJqdGkiOiJXVFdYVDNCT1JWSFNLQkc2T0pIVVdFQ01QRVdBNldZVEhNRzVEWkJBUUo1TUtGU1dHM1FRIiwiaWF0IjoxNTQ0MjE3NzU3LCJpc3MiOiJPQ0FUMzNNVFZVMlZVT0lNR05HVU5YSjY2QUgyUkxTREFGM01VQkNZQVk1UU1JTDY1TlFNNlhRRyIsInN1YiI6IkFDWlNXQko0U1lJTEs3UVZERUxPNjRWWDNFRldCNkNYQ1BNRUJVS0EzNk1KSlFSUFhHRUVRMldKIiwidHlwZSI6ImFjY291bnQiLCJuYXRzIjp7ImxpbWl0cyI6eyJzdWJzIjotMSwiY29ubiI6LTEsImltcG9ydHMiOi0xLCJleHBvcnRzIjotMSwiZGF0YSI6LTEsInBheWxvYWQiOi0xLCJ3aWxkY2FyZHMiOnRydWV9fX0.q-E7bBGTU0uoTmM9Vn7WaEHDzCUrqvPDb9mPMQbry_PNzVAjf0RG9vd15lGxW5lu7CuGVqpj4CYKhNDHluIJAg",
|
|
},
|
|
}, wsConfig());
|
|
const ns = await NatsServer.start(conf);
|
|
const nc = await connect(
|
|
{
|
|
servers: `ws://127.0.0.1:${ns.websocket}`,
|
|
authenticator: credsAuthenticator(new TextEncoder().encode(creds)),
|
|
},
|
|
);
|
|
await nc.flush();
|
|
await nc.close();
|
|
await ns.stop();
|
|
t.pass();
|
|
});
|
|
|
|
test("auth - custom", async (t) => {
|
|
const jwt =
|
|
"eyJ0eXAiOiJqd3QiLCJhbGciOiJlZDI1NTE5In0.eyJqdGkiOiJFU1VQS1NSNFhGR0pLN0FHUk5ZRjc0STVQNTZHMkFGWERYQ01CUUdHSklKUEVNUVhMSDJBIiwiaWF0IjoxNTQ0MjE3NzU3LCJpc3MiOiJBQ1pTV0JKNFNZSUxLN1FWREVMTzY0VlgzRUZXQjZDWENQTUVCVUtBMzZNSkpRUlBYR0VFUTJXSiIsInN1YiI6IlVBSDQyVUc2UFY1NTJQNVNXTFdUQlAzSDNTNUJIQVZDTzJJRUtFWFVBTkpYUjc1SjYzUlE1V002IiwidHlwZSI6InVzZXIiLCJuYXRzIjp7InB1YiI6e30sInN1YiI6e319fQ.kCR9Erm9zzux4G6M-V2bp7wKMKgnSNqMBACX05nwePRWQa37aO_yObbhcJWFGYjo1Ix-oepOkoyVLxOJeuD8Bw";
|
|
const useed = "SUAIBDPBAUTWCWBKIO6XHQNINK5FWJW4OHLXC3HQ2KFE4PEJUA44CNHTC4";
|
|
|
|
const conf = Object.assign({
|
|
operator:
|
|
"eyJ0eXAiOiJqd3QiLCJhbGciOiJlZDI1NTE5In0.eyJhdWQiOiJURVNUUyIsImV4cCI6MTg1OTEyMTI3NSwianRpIjoiWE5MWjZYWVBIVE1ESlFSTlFPSFVPSlFHV0NVN01JNVc1SlhDWk5YQllVS0VRVzY3STI1USIsImlhdCI6MTU0Mzc2MTI3NSwiaXNzIjoiT0NBVDMzTVRWVTJWVU9JTUdOR1VOWEo2NkFIMlJMU0RBRjNNVUJDWUFZNVFNSUw2NU5RTTZYUUciLCJuYW1lIjoiU3luYWRpYSBDb21tdW5pY2F0aW9ucyBJbmMuIiwibmJmIjoxNTQzNzYxMjc1LCJzdWIiOiJPQ0FUMzNNVFZVMlZVT0lNR05HVU5YSjY2QUgyUkxTREFGM01VQkNZQVk1UU1JTDY1TlFNNlhRRyIsInR5cGUiOiJvcGVyYXRvciIsIm5hdHMiOnsic2lnbmluZ19rZXlzIjpbIk9EU0tSN01ZRlFaNU1NQUo2RlBNRUVUQ1RFM1JJSE9GTFRZUEpSTUFWVk40T0xWMllZQU1IQ0FDIiwiT0RTS0FDU1JCV1A1MzdEWkRSVko2NTdKT0lHT1BPUTZLRzdUNEhONk9LNEY2SUVDR1hEQUhOUDIiLCJPRFNLSTM2TFpCNDRPWTVJVkNSNlA1MkZaSlpZTVlXWlZXTlVEVExFWjVUSzJQTjNPRU1SVEFCUiJdfX0.hyfz6E39BMUh0GLzovFfk3wT4OfualftjdJ_eYkLfPvu5tZubYQ_Pn9oFYGCV_6yKy3KMGhWGUCyCdHaPhalBw",
|
|
resolver: "MEMORY",
|
|
resolver_preload: {
|
|
ACZSWBJ4SYILK7QVDELO64VX3EFWB6CXCPMEBUKA36MJJQRPXGEEQ2WJ:
|
|
"eyJ0eXAiOiJqd3QiLCJhbGciOiJlZDI1NTE5In0.eyJqdGkiOiJXVFdYVDNCT1JWSFNLQkc2T0pIVVdFQ01QRVdBNldZVEhNRzVEWkJBUUo1TUtGU1dHM1FRIiwiaWF0IjoxNTQ0MjE3NzU3LCJpc3MiOiJPQ0FUMzNNVFZVMlZVT0lNR05HVU5YSjY2QUgyUkxTREFGM01VQkNZQVk1UU1JTDY1TlFNNlhRRyIsInN1YiI6IkFDWlNXQko0U1lJTEs3UVZERUxPNjRWWDNFRldCNkNYQ1BNRUJVS0EzNk1KSlFSUFhHRUVRMldKIiwidHlwZSI6ImFjY291bnQiLCJuYXRzIjp7ImxpbWl0cyI6eyJzdWJzIjotMSwiY29ubiI6LTEsImltcG9ydHMiOi0xLCJleHBvcnRzIjotMSwiZGF0YSI6LTEsInBheWxvYWQiOi0xLCJ3aWxkY2FyZHMiOnRydWV9fX0.q-E7bBGTU0uoTmM9Vn7WaEHDzCUrqvPDb9mPMQbry_PNzVAjf0RG9vd15lGxW5lu7CuGVqpj4CYKhNDHluIJAg",
|
|
},
|
|
}, wsConfig());
|
|
const ns = await NatsServer.start(conf);
|
|
const authenticator = (nonce) => {
|
|
const seed = nkeys.fromSeed(new TextEncoder().encode(useed));
|
|
const nkey = seed.getPublicKey();
|
|
const hash = seed.sign(new TextEncoder().encode(nonce));
|
|
const sig = nkeys.encode(hash);
|
|
|
|
return { nkey, sig, jwt };
|
|
};
|
|
const nc = await connect(
|
|
{
|
|
servers: `ws://127.0.0.1:${ns.websocket}`,
|
|
authenticator: authenticator,
|
|
},
|
|
);
|
|
await nc.flush();
|
|
await nc.close();
|
|
await ns.stop();
|
|
t.pass();
|
|
});
|
|
|
|
test("auth - jwt", async (t) => {
|
|
const jwt =
|
|
"eyJ0eXAiOiJqd3QiLCJhbGciOiJlZDI1NTE5In0.eyJqdGkiOiJFU1VQS1NSNFhGR0pLN0FHUk5ZRjc0STVQNTZHMkFGWERYQ01CUUdHSklKUEVNUVhMSDJBIiwiaWF0IjoxNTQ0MjE3NzU3LCJpc3MiOiJBQ1pTV0JKNFNZSUxLN1FWREVMTzY0VlgzRUZXQjZDWENQTUVCVUtBMzZNSkpRUlBYR0VFUTJXSiIsInN1YiI6IlVBSDQyVUc2UFY1NTJQNVNXTFdUQlAzSDNTNUJIQVZDTzJJRUtFWFVBTkpYUjc1SjYzUlE1V002IiwidHlwZSI6InVzZXIiLCJuYXRzIjp7InB1YiI6e30sInN1YiI6e319fQ.kCR9Erm9zzux4G6M-V2bp7wKMKgnSNqMBACX05nwePRWQa37aO_yObbhcJWFGYjo1Ix-oepOkoyVLxOJeuD8Bw";
|
|
const useed = "SUAIBDPBAUTWCWBKIO6XHQNINK5FWJW4OHLXC3HQ2KFE4PEJUA44CNHTC4";
|
|
|
|
const conf = Object.assign({
|
|
operator:
|
|
"eyJ0eXAiOiJqd3QiLCJhbGciOiJlZDI1NTE5In0.eyJhdWQiOiJURVNUUyIsImV4cCI6MTg1OTEyMTI3NSwianRpIjoiWE5MWjZYWVBIVE1ESlFSTlFPSFVPSlFHV0NVN01JNVc1SlhDWk5YQllVS0VRVzY3STI1USIsImlhdCI6MTU0Mzc2MTI3NSwiaXNzIjoiT0NBVDMzTVRWVTJWVU9JTUdOR1VOWEo2NkFIMlJMU0RBRjNNVUJDWUFZNVFNSUw2NU5RTTZYUUciLCJuYW1lIjoiU3luYWRpYSBDb21tdW5pY2F0aW9ucyBJbmMuIiwibmJmIjoxNTQzNzYxMjc1LCJzdWIiOiJPQ0FUMzNNVFZVMlZVT0lNR05HVU5YSjY2QUgyUkxTREFGM01VQkNZQVk1UU1JTDY1TlFNNlhRRyIsInR5cGUiOiJvcGVyYXRvciIsIm5hdHMiOnsic2lnbmluZ19rZXlzIjpbIk9EU0tSN01ZRlFaNU1NQUo2RlBNRUVUQ1RFM1JJSE9GTFRZUEpSTUFWVk40T0xWMllZQU1IQ0FDIiwiT0RTS0FDU1JCV1A1MzdEWkRSVko2NTdKT0lHT1BPUTZLRzdUNEhONk9LNEY2SUVDR1hEQUhOUDIiLCJPRFNLSTM2TFpCNDRPWTVJVkNSNlA1MkZaSlpZTVlXWlZXTlVEVExFWjVUSzJQTjNPRU1SVEFCUiJdfX0.hyfz6E39BMUh0GLzovFfk3wT4OfualftjdJ_eYkLfPvu5tZubYQ_Pn9oFYGCV_6yKy3KMGhWGUCyCdHaPhalBw",
|
|
resolver: "MEMORY",
|
|
resolver_preload: {
|
|
ACZSWBJ4SYILK7QVDELO64VX3EFWB6CXCPMEBUKA36MJJQRPXGEEQ2WJ:
|
|
"eyJ0eXAiOiJqd3QiLCJhbGciOiJlZDI1NTE5In0.eyJqdGkiOiJXVFdYVDNCT1JWSFNLQkc2T0pIVVdFQ01QRVdBNldZVEhNRzVEWkJBUUo1TUtGU1dHM1FRIiwiaWF0IjoxNTQ0MjE3NzU3LCJpc3MiOiJPQ0FUMzNNVFZVMlZVT0lNR05HVU5YSjY2QUgyUkxTREFGM01VQkNZQVk1UU1JTDY1TlFNNlhRRyIsInN1YiI6IkFDWlNXQko0U1lJTEs3UVZERUxPNjRWWDNFRldCNkNYQ1BNRUJVS0EzNk1KSlFSUFhHRUVRMldKIiwidHlwZSI6ImFjY291bnQiLCJuYXRzIjp7ImxpbWl0cyI6eyJzdWJzIjotMSwiY29ubiI6LTEsImltcG9ydHMiOi0xLCJleHBvcnRzIjotMSwiZGF0YSI6LTEsInBheWxvYWQiOi0xLCJ3aWxkY2FyZHMiOnRydWV9fX0.q-E7bBGTU0uoTmM9Vn7WaEHDzCUrqvPDb9mPMQbry_PNzVAjf0RG9vd15lGxW5lu7CuGVqpj4CYKhNDHluIJAg",
|
|
},
|
|
}, wsConfig());
|
|
const ns = await NatsServer.start(conf);
|
|
const nc = await connect(
|
|
{
|
|
servers: `ws://127.0.0.1:${ns.websocket}`,
|
|
authenticator: jwtAuthenticator(jwt, new TextEncoder().encode(useed)),
|
|
},
|
|
);
|
|
await nc.flush();
|
|
await nc.close();
|
|
await ns.stop();
|
|
t.pass();
|
|
});
|
|
|
|
test("auth - custom error", async (t) => {
|
|
t.plan(1);
|
|
const ns = await NatsServer.start(conf);
|
|
const authenticator = () => {
|
|
throw new Error("user code exploded");
|
|
};
|
|
await connect(
|
|
{
|
|
servers: `ws://127.0.0.1:${ns.websocket}`,
|
|
maxReconnectAttempts: 1,
|
|
authenticator: authenticator,
|
|
},
|
|
).then(() => {
|
|
t.fail("shouldn't have connected");
|
|
}).catch((err) => {
|
|
t.is(err.message, "user code exploded");
|
|
});
|
|
await ns.stop();
|
|
});
|
|
|
|
test("auth - ngs", async (t) => {
|
|
t.plan(1);
|
|
const token = process.env.WS_NGS_CI_USER || "";
|
|
if (token.length === 0) {
|
|
t.log("test skipped - no WS_NGS_CI_USER defined in the environment");
|
|
t.pass();
|
|
return;
|
|
} else {
|
|
t.log("token.len", token.length);
|
|
}
|
|
const sc = StringCodec();
|
|
const authenticator = jwtAuthenticator(token);
|
|
const nc1 = await connect({
|
|
servers: "wss://connect.ngs.global",
|
|
authenticator: authenticator,
|
|
});
|
|
const nc2 = await connect({
|
|
servers: "wss://connect.ngs.global",
|
|
authenticator: authenticator,
|
|
});
|
|
nc1.subscribe("hello.ngs", {
|
|
callback: (err, msg) => {
|
|
msg.respond(sc.encode("hi!"));
|
|
},
|
|
max: 1,
|
|
});
|
|
|
|
await nc1.flush();
|
|
const m = await nc2.request("hello.ngs");
|
|
t.is(sc.decode(m.data), "hi!");
|
|
await nc1.close();
|
|
await nc2.close();
|
|
});
|
|
|
|
test("auth - expiration notified", async (t) => {
|
|
const O = createOperator();
|
|
const A = createAccount();
|
|
|
|
const resolver = {};
|
|
resolver[A.getPublicKey()] = await encodeAccount("A", A, {
|
|
limits: {
|
|
conn: -1,
|
|
subs: -1,
|
|
},
|
|
}, { signer: O });
|
|
const conf = Object.assign({
|
|
operator: await encodeOperator("O", O),
|
|
resolver: "MEMORY",
|
|
"resolver_preload": resolver,
|
|
}, wsConfig());
|
|
|
|
const ns = await NatsServer.start(conf);
|
|
|
|
const U = createUser();
|
|
const ujwt = await encodeUser("U", U, A, { bearer_token: true }, {
|
|
exp: Math.round(Date.now() / 1000) + 5,
|
|
});
|
|
|
|
const nc = await connect({
|
|
servers: `ws://localhost:${ns.websocket}`,
|
|
maxReconnectAttempts: -1,
|
|
authenticator: jwtAuthenticator(ujwt),
|
|
});
|
|
|
|
let authErrors = 0;
|
|
(async () => {
|
|
for await (const s of nc.status()) {
|
|
if (
|
|
s.type === Events.Error && s.data === ErrorCode.AuthenticationExpired
|
|
) {
|
|
authErrors++;
|
|
}
|
|
}
|
|
})().then();
|
|
|
|
const err = await nc.closed();
|
|
t.true(authErrors >= 1);
|
|
await ns.stop();
|
|
});
|