• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nats-io / nats.js / 14248085491

03 Apr 2025 04:30PM UTC coverage: 84.536% (+0.002%) from 84.534%
14248085491

push

github

web-flow
Additional hardening of the object store client (#256)

* Additional hardening of the object store client

- made obj put publish messages sequentially - as current server can drop requests when the producer is too fast. This will degrade put performance.

- changed the internal push consumer used on get, to have an idle_heartbeat, if this fires, the get has stalled, and the ordered consumer should reset.

enabled flow control on the ordered consumer, this prevents slow consumers when the client is getting very large objects

Signed-off-by: Alberto Ricart <alberto@synadia.com>

* - hardening of the PullConsumer implementation, by default ordered consumers set flow control and idle_heartbeats. This enables the ordered consumer to self-recreate on `heartbeats_missed`, simplifying watcher/lister configurations.

- objectstore doesn't require listening to heartbeats_missed, since the pull consumer handles it automagically.

- objectstore watch added a check in watch for `heartbeat` notifications - if the watcher is only listing history this is a hint to stop as all records have been processed.

Signed-off-by: Alberto Ricart <alberto@synadia.com>

---------

Signed-off-by: Alberto Ricart <alberto@synadia.com>

2370 of 3217 branches covered (73.67%)

Branch coverage included in aggregate %.

10 of 23 new or added lines in 3 files covered. (43.48%)

4552 existing lines in 36 files now uncovered.

10170 of 11617 relevant lines covered (87.54%)

768618.27 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

85.95
/core/src/authenticator.ts
1
/*
2
 * Copyright 2020-2023 The NATS Authors
3
 * Licensed under the Apache License, Version 2.0 (the "License");
4
 * you may not use this file except in compliance with the License.
5
 * You may obtain a copy of the License at
6
 *
7
 * http://www.apache.org/licenses/LICENSE-2.0
8
 *
9
 * Unless required by applicable law or agreed to in writing, software
10
 * distributed under the License is distributed on an "AS IS" BASIS,
11
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
 * See the License for the specific language governing permissions and
13
 * limitations under the License.
14
 */
15
import { nkeys } from "./nkeys.ts";
55✔
16
import { TD, TE } from "./encoders.ts";
55✔
17
import type {
18
  Auth,
19
  Authenticator,
20
  JwtAuth,
21
  NKeyAuth,
22
  NoAuth,
23
  TokenAuth,
24
  UserPass,
25
} from "./core.ts";
26

UNCOV
27
export function multiAuthenticator(authenticators: Authenticator[]) {
53✔
UNCOV
28
  return (nonce?: string): Auth => {
131✔
UNCOV
29
    let auth: Partial<NoAuth & TokenAuth & UserPass & NKeyAuth & JwtAuth> = {};
242✔
UNCOV
30
    authenticators.forEach((a) => {
242✔
31
      const args = a(nonce) || {};
×
UNCOV
32
      auth = Object.assign(auth, args);
362✔
UNCOV
33
    });
242✔
UNCOV
34
    return auth as Auth;
242✔
UNCOV
35
  };
131✔
UNCOV
36
}
131✔
37

UNCOV
38
export function noAuthFn(): Authenticator {
54✔
UNCOV
39
  return (): NoAuth => {
674✔
UNCOV
40
    return;
1,301✔
UNCOV
41
  };
674✔
UNCOV
42
}
674✔
43

44
/**
45
 * Returns a user/pass authenticator for the specified user and optional password
46
 * @param { string | () => string } user
47
 * @param {string | () => string } pass
48
 * @return {UserPass}
49
 */
UNCOV
50
export function usernamePasswordAuthenticator(
53✔
UNCOV
51
  user: string | (() => string),
53✔
UNCOV
52
  pass?: string | (() => string),
53✔
53
): Authenticator {
UNCOV
54
  return (): UserPass => {
105✔
55
    const u = typeof user === "function" ? user() : user;
109✔
56
    const p = typeof pass === "function" ? pass() : pass;
109!
UNCOV
57
    return { user: u, pass: p };
652✔
UNCOV
58
  };
105✔
UNCOV
59
}
105✔
60

61
/**
62
 * Returns a token authenticator for the specified token
63
 * @param { string | () => string } token
64
 * @return {TokenAuth}
65
 */
66
export function tokenAuthenticator(
33✔
67
  token: string | (() => string),
33✔
68
): Authenticator {
69
  return (): TokenAuth => {
43✔
70
    const auth_token = typeof token === "function" ? token() : token;
61✔
71
    return { auth_token };
183✔
72
  };
43✔
73
}
43✔
74

75
/**
76
 * Returns an Authenticator that returns a NKeyAuth based that uses the
77
 * specified seed or function returning a seed.
78
 * @param {Uint8Array | (() => Uint8Array)} seed - the nkey seed
79
 * @return {NKeyAuth}
80
 */
UNCOV
81
export function nkeyAuthenticator(
51✔
UNCOV
82
  seed?: Uint8Array | (() => Uint8Array),
51✔
83
): Authenticator {
UNCOV
84
  return (nonce?: string): NKeyAuth => {
76✔
85
    const s = typeof seed === "function" ? seed() : seed;
82!
86
    const kp = s ? nkeys.fromSeed(s) : undefined;
82!
87
    const nkey = kp ? kp.getPublicKey() : "";
82!
88
    const challenge = TE.encode(nonce || "");
×
89
    const sigBytes = kp !== undefined && nonce ? kp.sign(challenge) : undefined;
82!
90
    const sig = sigBytes ? nkeys.encode(sigBytes) : "";
82!
UNCOV
91
    return { nkey, sig };
408✔
UNCOV
92
  };
76✔
UNCOV
93
}
76✔
94

95
/**
96
 * Returns an Authenticator function that returns a JwtAuth.
97
 * If a seed is provided, the public key, and signature are
98
 * calculated.
99
 *
100
 * @param {string | ()=>string} ajwt - the jwt
101
 * @param {Uint8Array | ()=> Uint8Array } seed - the optional nkey seed
102
 * @return {Authenticator}
103
 */
UNCOV
104
export function jwtAuthenticator(
51✔
UNCOV
105
  ajwt: string | (() => string),
51✔
UNCOV
106
  seed?: Uint8Array | (() => Uint8Array),
51✔
107
): Authenticator {
UNCOV
108
  return (
68✔
UNCOV
109
    nonce?: string,
68✔
110
  ): JwtAuth => {
111
    const jwt = typeof ajwt === "function" ? ajwt() : ajwt;
69!
UNCOV
112
    const fn = nkeyAuthenticator(seed);
89✔
UNCOV
113
    const { nkey, sig } = fn(nonce) as NKeyAuth;
89✔
UNCOV
114
    return { jwt, nkey, sig };
445✔
UNCOV
115
  };
68✔
UNCOV
116
}
68✔
117

118
/**
119
 * Returns an Authenticator function that returns a JwtAuth.
120
 * This is a convenience Authenticator that parses the
121
 * specified creds and delegates to the jwtAuthenticator.
122
 * @param {Uint8Array | () => Uint8Array } creds - the contents of a creds file or a function that returns the creds
123
 * @returns {JwtAuth}
124
 */
125
export function credsAuthenticator(
33✔
126
  creds: Uint8Array | (() => Uint8Array),
33✔
127
): Authenticator {
128
  const fn = typeof creds !== "function" ? () => creds : creds;
42✔
129
  const parse = () => {
42✔
130
    const CREDS =
55✔
131
      /\s*(?:(?:[-]{3,}[^\n]*[-]{3,}\n)(.+)(?:\n\s*[-]{3,}[^\n]*[-]{3,}\n))/ig;
55✔
132
    const s = TD.decode(fn());
55✔
133
    // get the JWT
134
    let m = CREDS.exec(s);
55✔
135
    if (!m) {
55✔
136
      throw new Error("unable to parse credentials");
56✔
137
    }
56✔
138
    const jwt = m[1].trim();
67✔
139
    // get the nkey
140
    m = CREDS.exec(s);
67✔
141
    if (!m) {
×
142
      throw new Error("unable to parse credentials");
×
143
    }
✔
144
    const seed = TE.encode(m[1].trim());
67✔
145

146
    return { jwt, seed };
268✔
147
  };
42✔
148

149
  const jwtFn = () => {
42✔
150
    const { jwt } = parse();
49✔
151
    return jwt;
49✔
152
  };
42✔
153
  const nkeyFn = () => {
42✔
154
    const { seed } = parse();
48✔
155
    return seed;
48✔
156
  };
42✔
157

158
  return jwtAuthenticator(jwtFn, nkeyFn);
42✔
159
}
42✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc