Skip to content

Commit

Permalink
[FEAT] added connect option ignoreAuthErrorAbort which disables a c…
Browse files Browse the repository at this point in the history
…onnection abort if client fails to authenticate twice with the same error.
  • Loading branch information
aricart committed Nov 17, 2022
1 parent 0471b24 commit 48eab8f
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 6 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ jobs:
run: echo "NATS_VERSION=v2.9.5" >> $GITHUB_ENV

# this here because dns seems to be wedged on gha
- name: Add hosts to /etc/hosts
run: |
sudo echo "145.40.102.131 demo.nats.io" | sudo tee -a /etc/hosts
# - name: Add hosts to /etc/hosts
# run: |
# sudo echo "145.40.102.131 demo.nats.io" | sudo tee -a /etc/hosts

- name: Get nats-server
run: |
Expand Down
1 change: 1 addition & 0 deletions nats-base-client/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export function defaultOptions(): ConnectionOptions {
tls: undefined,
verbose: false,
waitOnFirstConnect: false,
ignoreAuthErrorAbort: false,
} as ConnectionOptions;
}

Expand Down
5 changes: 4 additions & 1 deletion nats-base-client/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,10 @@ export class ProtocolHandler implements Dispatcher<ParserEvent> {
}

handleAuthError(err: NatsError) {
if (this.lastError && err.code === this.lastError.code) {
if (
(this.lastError && err.code === this.lastError.code) &&
this.options.ignoreAuthErrorAbort === false
) {
this.abortReconnect = true;
}
if (this.connectError) {
Expand Down
7 changes: 7 additions & 0 deletions nats-base-client/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,13 @@ export interface ConnectionOptions {
* to specify a subject where requests can deliver responses.
*/
inboxPrefix?: string;

/**
* By default, NATS clients will abort reconnect if they fail authentication
* twice in a row with the same error, regardless of the reconnect policy.
* This option should be used with care as it will disable this behaviour when true
*/
ignoreAuthErrorAbort?: boolean;
}

/**
Expand Down
57 changes: 55 additions & 2 deletions tests/auth_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,25 @@ import {
UserPass,
} from "../src/mod.ts";
import { assertErrorCode, NatsServer } from "./helpers/mod.ts";
import { deferred, nkeys } from "../nats-base-client/internal_mod.ts";
import { NKeyAuth } from "../nats-base-client/authenticator.ts";
import {
deferred,
delay,
NatsConnectionImpl,
nkeys,
} from "../nats-base-client/internal_mod.ts";
import {
buildAuthenticator,
NKeyAuth,
} from "../nats-base-client/authenticator.ts";
import { assert } from "../nats-base-client/denobuffer.ts";
import { cleanup, setup } from "./jstest_util.ts";
import {
encodeAccount,
encodeOperator,
encodeUser,
} from "https://raw.githubusercontent.com/nats-io/jwt.js/main/src/jwt.ts";
import { Msg } from "https://deno.land/x/[email protected]/nats-base-client/types.ts";
import { DEFAULT_MAX_RECONNECT_ATTEMPTS } from "../nats-base-client/types.ts";

const conf = {
authorization: {
Expand Down Expand Up @@ -968,3 +978,46 @@ Deno.test("auth - perm sub iterator error", async () => {

await cleanup(ns, nc);
});

Deno.test("auth - ignore auth error abort", async () => {
const ns = await NatsServer.start({
authorization: {
users: [{
user: "a",
password: "a",
}],
},
});
async function t(ignoreAuthErrorAbort = false): Promise<number> {
let pass = "a";
const authenticator = (): UserPass => {
return { user: "a", pass };
};
const nc = await connect({
port: ns.port,
authenticator,
ignoreAuthErrorAbort,
reconnectTimeWait: 150,
});

let count = 0;
(async () => {
for await (const s of nc.status()) {
if (s.type === "error" && s.data === "AUTHORIZATION_VIOLATION") {
count++;
}
}
})().then();

const nci = nc as NatsConnectionImpl;
pass = "b";
nci.protocol.transport.disconnect();

await nc.closed();
return count;
}

assertEquals(await t(), 2);
assertEquals(await t(true), DEFAULT_MAX_RECONNECT_ATTEMPTS);
await ns.stop();
});

0 comments on commit 48eab8f

Please sign in to comment.