@mcp-abap-adt/auth-broker 4.1.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,13 +3,20 @@
3
3
  *
4
4
  * `getProvider` builds the `IAuthProvider` a destination states, from the
5
5
  * means its service key store holds and the secret its session store holds.
6
- * Every token provider it builds writes what it obtains back to the session
7
- * store through `onTokens` — the secret alone, retried by the broker when the
8
- * store fails (`SessionWriter`); `flush()` reports what is still pending.
6
+ * Every token provider it builds renews through the consumer's `renewal` and
7
+ * writes what it obtains back to the session store through auth-providers'
8
+ * `refreshStatePersistence` — the secret alone, through one plain queue per
9
+ * destination (`SessionWriter`): a failed write stays pending until the
10
+ * destination's next write or `flush()`, and means what the consumer's
11
+ * `onWriteFailure` says; `flush()` reports what is still pending.
9
12
  * The token API (`getToken`, `refreshToken`, `createTokenRefresher`) asks that
10
- * same provider — one per destination, shared — or, when the consumer gives
11
- * one, the consumer's provider, whose every answer it writes through the same
12
- * path.
13
+ * same provider — the row path's — or, when the consumer gives one, the
14
+ * consumer's provider — the consumer path's, resolved, cached and bound on its
15
+ * own — whose every answer it writes through the same write path.
16
+ *
17
+ * A provider is never changed: every call re-reads what its path's
18
+ * provider was built from and builds a new one, starting with nothing, when
19
+ * anything of it changed (`buildIdentity.ts`).
13
20
  *
14
21
  * The broker orchestrates and nothing more. It resolves what the stores know
15
22
  * about a destination, hands it to the provider, asks the provider for a token
@@ -22,23 +29,45 @@ import type { IDeviceCodePresenter, OidcCallbackResult } from '@mcp-abap-adt/aut
22
29
  import type { IAssertionReplayStore, IAuthorizationStrategy, IAuthProvider, IClientAuthentication, IRefreshableTokenProvider, ITokenRefresher } from '@mcp-abap-adt/interfaces-auth';
23
30
  import type { ILogger } from '@mcp-abap-adt/interfaces-utils';
24
31
  import { type ClientAuthenticationStrategy } from './clientAuthentication';
32
+ import { type RenewalOption } from './destinations';
25
33
  import type { IAuthorizationConfig, IConnectionConfig, IServiceKeyStore, ISessionStore } from './stores/interfaces';
34
+ /** What a caller of `getProvider`, the token API and `flush()` may pass. */
35
+ export interface BrokerCallOptions {
36
+ /**
37
+ * This caller no longer needs the answer: an abort releases this caller
38
+ * alone, with auth-errors' `aborted` failure (`interactive-login`), while
39
+ * the work it waited on runs on for the others. No bound of the broker's
40
+ * own: a caller that wants one passes `AbortSignal.timeout(ms)`.
41
+ */
42
+ readonly signal?: AbortSignal | undefined;
43
+ }
26
44
  /**
27
- * Builds the provider for one destination, from what the stores hold for it.
45
+ * Builds the token API's provider for one destination, from the means and the
46
+ * client — never from a stored secret: the consumer path is never seeded
47
+ *. A consumer whose provider must resume after a restart composes that
48
+ * itself: its provider's own seed and persistence.
49
+ *
50
+ * It is handed exactly these, and nothing else a store answered:
28
51
  *
29
- * - `authConfig`: the UAA credentials — from the session when it holds them,
30
- * else from the service key — with the refresh token the session stored, or
31
- * `null` when neither store has credentials (a SAML flow needs none).
32
- * - `connConfig`: the session's connection config, with `serviceUrl` resolved
33
- * and the last token the session stored, so the provider can reuse it while
34
- * it is valid.
35
- * - `client` (optional): passed only beside a `clientAuthentication` strategy,
36
- * for a destination whose grant authenticates a client — the strategy's
37
- * answer, the client identity and the bound refresh token; never PEM. See
38
- * `TokenProviderClient`. Without a strategy the factory gets three
39
- * arguments, as 4.0.0.
52
+ * - `authConfig`: the client, through an allowlist — `uaaUrl`, `uaaClientId`,
53
+ * `uaaClientSecret` — from the session store when it answers one, else from
54
+ * the key store; `refreshToken` is a key, never a value. `null` when
55
+ * neither store has a client (a SAML flow needs none).
56
+ * - `connConfig`: the connection means, through an allowlist — `serviceUrl`
57
+ * (resolved: the session's, else the key store's), and, as the session
58
+ * store's connection config states them, `sapClient`, `language`,
59
+ * `authType` and `grantType`. No token, cookies, expiry, refresh token or
60
+ * binding, nor any other field.
61
+ * - `client` (`TokenProviderClient`), only beside a `clientAuthentication`
62
+ * strategy, for a destination whose grant authenticates a client: the
63
+ * strategy's answer and the client identity (`uaaUrl`, `clientId`); never
64
+ * PEM, never a secret, never a refresh token. Without a strategy the
65
+ * factory gets three arguments, as 4.0.0.
40
66
  *
41
- * Called once per destination; the broker keeps the provider it returns.
67
+ * Called once per build: the broker keeps the provider it returns while what
68
+ * it was handed is unchanged, re-reading it on every token API call;
69
+ * when any of it changes, the factory is called again and the new provider
70
+ * starts with nothing.
42
71
  */
43
72
  export type TokenProviderFactory = (destination: string, authConfig: IAuthorizationConfig | null, connConfig: IConnectionConfig, client?: TokenProviderClient) => IRefreshableTokenProvider;
44
73
  /**
@@ -58,10 +87,8 @@ export interface TokenProviderClient {
58
87
  /** The client id beside `uaaUrl`, from the same client. */
59
88
  readonly clientId?: string;
60
89
  /**
61
- * The refresh token the session stored, only when the session is bound to
62
- * this resource and this client identity — as `authConfig` carries it on
63
- * the strategy path for a secret client, so a certificate client, whose
64
- * `authConfig` is `null`, gets it too.
90
+ * Never set — not even as a key: the consumer path is handed no stored
91
+ * secret. Kept in the type, which 5.0.0 leaves unchanged.
65
92
  */
66
93
  readonly refreshToken?: string;
67
94
  }
@@ -81,31 +108,33 @@ export interface AuthBrokerConfig {
81
108
  * basic's user and password, the SNC fields, `serviceUrl`. `getProvider`
82
109
  * needs it: there is no other source of means.
83
110
  */
84
- serviceKeyStore?: IServiceKeyStore;
111
+ serviceKeyStore?: IServiceKeyStore | undefined;
85
112
  /**
86
113
  * The token API's source: the token provider, or a factory building one per
87
114
  * destination. Not used by `getProvider`, which builds what the destination
88
115
  * states.
89
116
  *
90
- * An instance is used as given, for every destination. A factory is seeded
91
- * with what the stores hold for the destination (see `TokenProviderFactory`).
117
+ * An instance is used as given, for every destination. A factory is handed
118
+ * the destination's means and client, never a stored secret (see
119
+ * `TokenProviderFactory`).
92
120
  */
93
- provider?: IRefreshableTokenProvider | TokenProviderFactory;
121
+ provider?: IRefreshableTokenProvider | TokenProviderFactory | undefined;
94
122
  /** The interactive strategy of the UAA code, passcode and SAML grants. */
95
- authorization?: (destination: string, grant: StrategyGrant) => IAuthorizationStrategy<string>;
123
+ authorization?: ((destination: string, grant: StrategyGrant) => IAuthorizationStrategy<string>) | undefined;
96
124
  /** The interactive strategy of the OIDC authorization code grant. */
97
- oidcAuthorization?: (destination: string) => IAuthorizationStrategy<OidcCallbackResult>;
125
+ oidcAuthorization?: ((destination: string) => IAuthorizationStrategy<OidcCallbackResult>) | undefined;
98
126
  /** Where the device flow shows the user its code. */
99
- deviceCodePresenter?: (destination: string) => IDeviceCodePresenter;
127
+ deviceCodePresenter?: ((destination: string) => IDeviceCodePresenter) | undefined;
100
128
  /** `saml2_pure`: turns the SAMLResponse into the system's session cookies. */
101
- samlCookies?: (destination: string) => (samlResponse: string) => Promise<string>;
129
+ samlCookies?: ((destination: string) => (samlResponse: string) => Promise<string>) | undefined;
102
130
  /** The replay store the SAML assertion validators share. */
103
- assertionReplayStore?: (destination: string) => IAssertionReplayStore;
131
+ assertionReplayStore?: ((destination: string) => IAssertionReplayStore) | undefined;
104
132
  /**
105
133
  * How a destination's client authenticates to the authorization server, for
106
134
  * every grant that authenticates one (`ClientAuthenticationGrant`). Called
107
- * once when the destination's provider is built, with the client the key
108
- * store answers and its certificate, read only if the strategy asks.
135
+ * once per build of the destination's provider, with the client the key
136
+ * store answers and its certificate, read only if the strategy asks — and
137
+ * then re-read on every call, a change building a new provider.
109
138
  *
110
139
  * A given strategy always answers one, or throws: there is no "nothing"
111
140
  * answer, so an explicit choice never falls back to the secret. A throw
@@ -120,7 +149,41 @@ export interface AuthBrokerConfig {
120
149
  * An instance given as `provider` is already composed by the consumer, so
121
150
  * the token API uses it as given and calls no strategy for it.
122
151
  */
123
- clientAuthentication?: ClientAuthenticationStrategy;
152
+ clientAuthentication?: ClientAuthenticationStrategy | undefined;
153
+ /**
154
+ * How the provider the broker builds for a destination renews: called once
155
+ * per build of every token row (the UAA, OIDC and SAML grants), with the
156
+ * destination and the grant it states; the answer is the provider's
157
+ * `renewal`, unchanged. Required for those rows — there is no default: a
158
+ * token row built without it is refused naming `renewal`. `() =>
159
+ * refreshThenLogin()` is what 4.x did; `refreshOnly()` never logs in. Not
160
+ * called for `basic`, `snc` or `none`, nor for the token API's `provider`,
161
+ * which brings its own.
162
+ */
163
+ renewal?: RenewalOption | undefined;
164
+ /**
165
+ * What a session write that did not land means — `'fail'`: the call that
166
+ * caused it fails (`unknown`, `persisting-tokens`), and while the
167
+ * destination's write is pending every `getProvider` / `getToken` /
168
+ * `refreshToken` of it retries the write first, and once more right before
169
+ * it succeeds, and is refused while it fails; `'continue'`: it is logged
170
+ * and the call goes on. Either way the write stays pending until the
171
+ * destination's next write or `flush()` — nothing retries it on its own.
172
+ * Required for every destination
173
+ * that writes a secret — a token row built by `getProvider`, and every call
174
+ * of the token API; no default.
175
+ */
176
+ onWriteFailure?: 'fail' | 'continue' | undefined;
177
+ /**
178
+ * Passed to every token provider the broker builds; on only for `true`
179
+ * itself — absent, `false`, `'true'` or `1` is off. Never read from the
180
+ * environment. With it, a provider's one debug line for a refused token
181
+ * request names the request's secrets in its prepared form (the first and
182
+ * last four characters around a length marker), never the server's text;
183
+ * the line goes to the broker's logger. A consumer's `provider` — an
184
+ * instance or what a factory builds — keeps its own setting.
185
+ */
186
+ authDebug?: boolean | undefined;
124
187
  }
125
188
  /**
126
189
  * AuthBroker manages authentication tokens for destinations
@@ -130,29 +193,37 @@ export declare class AuthBroker {
130
193
  private readonly serviceKeyStore;
131
194
  private readonly sessionStore;
132
195
  private readonly provider;
133
- /** A consumer factory's providers: the promise of the build, as `built`. */
134
- private readonly consumerBuilt;
196
+ /** Per (destination, path): the provider handed out while unchanged. */
197
+ private readonly resolvedRow;
198
+ private readonly resolvedConsumer;
135
199
  /**
136
- * One cache per destination, shared by `getProvider` and — when the
137
- * consumer gives no provider — the token API: the promise of the
138
- * build, set before its first read.
200
+ * Per (destination, path): the slot of shared resolutions — every
201
+ * caller of that path is a waiter of its attempt.
139
202
  */
140
- private readonly built;
203
+ private readonly rowSlots;
204
+ private readonly consumerSlots;
205
+ /** The broker-wide slot every `flush()` caller joins. */
206
+ private readonly flushSlot;
207
+ /** Per (destination, path): the last generation a build took. */
208
+ private readonly generations;
209
+ /** Per (destination, path): the newest generation that queued a write. */
210
+ private readonly newestWriter;
141
211
  /**
142
- * The write that failed for a result, keyed on the result the provider
143
- * handed over and returns, then on the destination it was written
144
- * for: the token API throws it to its caller, as 3.x did, while the broker
145
- * keeps retrying. Dropped once a write of that result for that destination
146
- * lands.
212
+ * The destinations whose means changed under the consumer's instance: the
213
+ * token API refuses them until a new broker.
147
214
  */
148
- private readonly failedWrites;
215
+ private readonly instanceRefused;
149
216
  private readonly authorization;
150
217
  private readonly oidcAuthorization;
151
218
  private readonly deviceCodePresenter;
152
219
  private readonly samlCookies;
153
220
  private readonly assertionReplayStore;
154
221
  private readonly clientAuthentication;
155
- /** getProvider's writes of the session secret, retried on their own. */
222
+ private readonly renewal;
223
+ private readonly onWriteFailure;
224
+ /** `config.authDebug === true`: what every token provider it builds is told. */
225
+ private readonly authDebug;
226
+ /** Every write of the session secret: one plain queue per destination. */
156
227
  private readonly writer;
157
228
  /**
158
229
  * @param config Stores and the provider (instance or factory)
@@ -165,26 +236,52 @@ export declare class AuthBroker {
165
236
  *
166
237
  * Without a consumer `provider`, the provider is the one `getProvider` hands
167
238
  * out for the destination — the same instance, so one token and one renewal
168
- * serve both — and what it obtains is written by its `onTokens`. With one,
239
+ * serve both — and what it obtains is written by its persistence. With one,
169
240
  * the consumer's provider is asked and its answer written, as in 3.x — the
170
241
  * secret alone.
171
242
  *
172
- * Errors from the provider (its typed errors included) propagate unchanged;
173
- * so does a store failure, a failed write of the token included — the token
174
- * stands and the broker keeps retrying the write.
243
+ * A provider's failure is relayed as the same object; a store's read
244
+ * failure reaches the caller as the store raised it. A write that did not
245
+ * land fails the call under `onWriteFailure: 'fail'` (`unknown`,
246
+ * `persisting-tokens`) — the token stands, and the write stays pending: the
247
+ * destination's next call retries it first and is refused while it fails —
248
+ * and is only logged under `'continue'`.
175
249
  *
176
250
  * @throws DestinationConfigError for a destination the key store states as
177
- * `basic` or `snc`, before any provider is asked; without a consumer
178
- * `provider`, also for one whose provider obtains no token.
251
+ * `basic` or `snc`, before any provider is asked; without the
252
+ * `onWriteFailure` option; without a consumer `provider`, also for one
253
+ * whose provider obtains no token.
179
254
  */
180
- getToken(destination: string): Promise<string>;
255
+ getToken(destination: string, options?: BrokerCallOptions): Promise<string>;
181
256
  /**
182
257
  * A new token for the destination, never the cached one — for a caller whose
183
258
  * token the server has just refused. Calls the provider's `refreshTokens()`;
184
259
  * a renewal already in flight for the destination is joined, not repeated.
185
260
  */
186
- refreshToken(destination: string): Promise<string>;
261
+ refreshToken(destination: string, options?: BrokerCallOptions): Promise<string>;
262
+ /**
263
+ * The token API's one body. The call's signal releases this caller from
264
+ * every wait it has — the write checks, the means read, the resolution
265
+ * (whose waiter it is, never attaching), its own write — and is
266
+ * passed to the provider's `getTokens` / `refreshTokens`.
267
+ */
187
268
  private obtain;
269
+ /**
270
+ * Under `onWriteFailure: 'fail'`, a call of the destination is refused while
271
+ * its last write is pending — not yet landed: failed, or still queued
272
+ * or in flight. Asked on entry and right before success: the call awaits
273
+ * every write of the destination queued before this moment, and a failed
274
+ * one that no later write replaced is written once more — the destination's
275
+ * next write, queued like any other. All landed: on entry the call goes on,
276
+ * at the end it returns its success. Still failing: it rejects (`unknown`,
277
+ * `persisting-tokens`). A write queued after the check is not this call's.
278
+ * Under `'continue'` nothing is asked.
279
+ *
280
+ * The one wait is `writer.retry(destination)`'s promise, a waiter of its
281
+ * own slot with the call's signal: an abort releases the caller
282
+ * (`aborted`), never with success, and the write runs on.
283
+ */
284
+ private settlePending;
188
285
  /**
189
286
  * The destination's means, read first: a destination the key store states
190
287
  * as `basic` or `snc` holds no token, so the token API refuses it before any
@@ -193,26 +290,57 @@ export declare class AuthBroker {
193
290
  * a 3.x setup, served as before.
194
291
  */
195
292
  private statedForTokens;
196
- /** The token API on `getProvider`'s provider. */
293
+ /**
294
+ * The token API on the row path's provider — the one `getProvider` hands
295
+ * out, resolved the same way, never through `getProvider` itself.
296
+ */
197
297
  private obtainShared;
198
298
  /**
199
- * The token API on the consumer's provider, as 3.x: the session read first,
200
- * then the key store, for `serviceUrl` and the client; every answer — a
201
- * cache hit included — written, the secret alone, through the broker's one
202
- * write path.
299
+ * The token API on the consumer's provider: resolved on the consumer path,
300
+ * every answer — a cache hit included — written, the secret alone, through
301
+ * the broker's one write path, with the binding fixed when the provider was
302
+ * taken into use.
203
303
  */
204
304
  private obtainFromConsumer;
205
- /** The failure recorded for this result's write here, thrown as the store raised it. */
206
- private throwFailedWrite;
207
305
  /**
208
- * The consumer's provider for the destination, cached per destination as a
209
- * promise set before its first read and dropped when it throws, so
210
- * the next call builds again: a factory's build — handed the client resolved
211
- * then — or an instance as given, for every destination, handed no client.
212
- * Either way the binding is fixed here, from the `serviceUrl`, SAP client and
213
- * client of this first call, and kept with the provider.
306
+ * The slot of one (destination, path)'s resolutions: a caller of
307
+ * the path arriving while an attempt is active joins it; when every caller
308
+ * of an attempt has aborted, the attempt leaves the slot at once and the
309
+ * next caller starts afresh. A failed or aborted resolution is not kept.
214
310
  */
215
- private consumerProviderFor;
311
+ private slotOf;
312
+ /** Whether a build of this path was ever committed for the destination. */
313
+ private everBuilt;
314
+ /** A committed build's generation, from its path's counter. */
315
+ private nextGeneration;
316
+ /**
317
+ * Queues one write of a build of `path`. A write of a build older than the
318
+ * newest build of the same path that has queued a write for the destination
319
+ * is dropped — never written, never pending; a build of the other
320
+ * path never retires this one. A dropped write is not a failed one: the
321
+ * retired provider's holder keeps it, and the destination's session
322
+ * is the newer build's.
323
+ */
324
+ private submit;
325
+ /** This call's store reads: each source read at most once. */
326
+ private storeReads;
327
+ /**
328
+ * The consumer path's provider for the destination: the cached one
329
+ * while everything it was built from is unchanged; else, for a factory, a
330
+ * new build — the factory called again, its provider starting with nothing
331
+ * — and, for an instance, which cannot be rebuilt, a refusal naming
332
+ * `provider` until a new broker.
333
+ */
334
+ private resolveConsumer;
335
+ /**
336
+ * Takes the consumer's provider into use for the destination: a factory's
337
+ * build — handed the means and the client, never a stored secret — or an
338
+ * instance as given, handed nothing. The binding is fixed here, from the
339
+ * `serviceUrl` (the session's, else the key store's), the SAP client and
340
+ * the client of this build. Every store answer is read through `recorder`:
341
+ * what it read is the build's identity.
342
+ */
343
+ private buildConsumer;
216
344
  /**
217
345
  * The token API's strategy path: with a `clientAuthentication` strategy and a
218
346
  * destination stating a grant whose client authenticates, the strategy's
@@ -231,17 +359,24 @@ export declare class AuthBroker {
231
359
  /**
232
360
  * What a consumer's factory's credentials are composed from, read in the
233
361
  * 3.x order: the session's authorization config; only when it has none, the
234
- * session and then the key store's client. A session store of auth-stores 3
362
+ * key store's client. The stored session is not read: nothing of it is
363
+ * handed to the factory. A session store of auth-stores 3
235
364
  * answers no client, so the key store's is what is found.
236
365
  */
237
366
  private readAuthorization;
238
- /** The session the store holds for the destination, or null. */
239
- private loadStoredSession;
367
+ /**
368
+ * What the consumer path takes from its stores for one destination, read
369
+ * from `reads` — the same function for a build and for every later call's
370
+ * comparison: the means, the `serviceUrl` (the session's, else the key
371
+ * store's), the SAP client, the row, the client through its allowlist, and
372
+ * the factory's seed of allowlisted connection means.
373
+ */
374
+ private consumerInputs;
240
375
  /**
241
376
  * `serviceUrl` for a consumer's provider, in the 3.x order: the session's,
242
377
  * else the key store's, else an error before the provider is asked.
243
378
  */
244
- private resolveServiceUrl;
379
+ private serviceUrlOf;
245
380
  /**
246
381
  * A store read where absence is an answer and anything else is not.
247
382
  *
@@ -275,56 +410,104 @@ export declare class AuthBroker {
275
410
  * built from the means the service key store holds and the secret the
276
411
  * session store holds.
277
412
  *
278
- * One provider per destination for the broker's life: concurrent first calls
279
- * share one build, and a build that threw is tried again on the next call.
413
+ * A provider is never changed: every call re-reads what the
414
+ * destination's provider was built from — the means, the client, and the
415
+ * certificate client when the build read it — and answers the cached
416
+ * provider while all of it is unchanged. When anything changed, by a single
417
+ * character, it builds a new provider, which starts with nothing — no token,
418
+ * no refresh token, nothing of the old provider or of a session written
419
+ * under other means — and never hands the old one out again; whoever holds
420
+ * it keeps it, and its writes are dropped once the new one has written.
421
+ * Concurrent calls share one resolution; a resolution that threw is tried
422
+ * again on the next call.
280
423
  *
281
424
  * A token provider (the UAA, OIDC and SAML grants) is seeded from the
282
- * session when the stored secret is bound to this destination, and writes
283
- * every token it obtains — at `prepare()`, on expiry, or in `rejected()` after
284
- * a 401 — back to the session store before it answers (see `flush()`).
425
+ * session only at its destination's first build in this broker, and only
426
+ * when the stored secret is bound to exactly this build's means (fully
427
+ * stated); it writes every token it obtains — at `prepare()`, on expiry, or
428
+ * in `rejected()` after a 401 — back to the session store before it answers
429
+ * (see `flush()`).
430
+ *
431
+ * `options.signal` releases this caller from every wait (`aborted`), and is
432
+ * attached to the token or SNC provider answered — built or cached — so a
433
+ * login it starts later is aborted once every session holding it has gone
434
+ *. Without a signal nothing is attached.
285
435
  *
286
436
  * @throws DestinationConfigError when the destination lacks what its type
287
437
  * needs — naming the fields or options, never a value.
288
438
  */
289
- getProvider(destination: string): Promise<IAuthProvider>;
439
+ getProvider(destination: string, options?: BrokerCallOptions): Promise<IAuthProvider>;
440
+ /**
441
+ * The row path's provider for the destination: the cached one while what
442
+ * its build read is unchanged, else a new build, committed with the
443
+ * next generation of the row path.
444
+ */
445
+ private resolveRow;
446
+ /**
447
+ * One build of the destination's row. Every store answer it reads goes
448
+ * through `recorder` — what it read is its identity. `seeded`: whether the
449
+ * build may start from the stored session; `commit`: the generation its
450
+ * writes carry, set when the build is committed; `signal`: the build's
451
+ * attempt, handed to the `clientAuthentication` strategy. Answers
452
+ * the provider and the row it stated.
453
+ */
290
454
  private build;
455
+ /**
456
+ * A token row's refusal when the consumer's `renewal` or `onWriteFailure`
457
+ * is missing — named beside every other field and option the row lacks, in
458
+ * one error — decided before any collaborator is called. With a
459
+ * clientAuthentication strategy and no secret client, the client's fields
460
+ * are not judged: the strategy would tell the certificate client's.
461
+ */
462
+ private rowRefusal;
291
463
  /**
292
464
  * The stored secret when it is bound to this destination's resource and
293
465
  * issuer, else `null`: the provider is then built as with no session
294
- * and logs in afresh — the refresh token is not spent either. The log line
295
- * names the destination only: never a URI, never a token.
466
+ * and logs in afresh — the refresh token is not spent either.
467
+ *
468
+ * A stored credential not taken is logged in fixed words naming the
469
+ * destination only — never a URI, a record or a token: a `warn` when the
470
+ * binding could ever be seeded (`couldBeSeeded`) — the stored secret is not
471
+ * recorded under the current means: another resource, row, client,
472
+ * endpoint or trust, a 4.x record, or none — and a `debug` line when it
473
+ * never could — a row never seeded by design (`token_exchange`), means
474
+ * lacking what the record needs, or no `serviceUrl` — since that holds on
475
+ * every start and nothing was discarded by a change.
296
476
  */
297
477
  private boundOrDiscarded;
298
478
  /**
299
- * Waits for the session writes still pending — each gets one more attempt —
300
- * and rejects naming the destinations whose store still refuses. Call it on
301
- * shutdown to know whether every token a provider obtained is stored; the
302
- * broker keeps retrying after a rejection.
479
+ * Waits for every session write queued so far and gives each pending one —
480
+ * a write that did not land — one more attempt; rejects naming the
481
+ * destinations whose store still refuses (an `AggregateError` of
482
+ * `SessionWriteFailure`s). Nothing retries a pending write on its own: only
483
+ * the destination's next write or `flush()` does, so call it on shutdown to
484
+ * know whether every token a provider obtained is stored.
485
+ *
486
+ * Every caller joins one broker-wide slot: its signal releases that
487
+ * caller alone (`aborted`); the attempts run on, and a write still failing
488
+ * stays pending. The `AggregateError` is rethrown as the same object to
489
+ * every caller.
303
490
  */
304
- flush(): Promise<void>;
491
+ flush(options?: BrokerCallOptions): Promise<void>;
305
492
  /**
306
- * One write of the destination's session secret — and nothing else:
307
- * `{ authorizationToken, expiresAt, refreshToken, issuedFor, issuedBy }` in
308
- * one `saveSession` — or, for a `saml2_pure` result (`tokenType: 'saml'`),
309
- * `{ sessionCookies, expiresAt, issuedFor, issuedBy }`: cookies are written
310
- * as cookies, every other result as a token (`saml2_bearer` included). No means is ever written: not `serviceUrl`, not
311
- * `authType`, not the client — they live in the key store, which the broker
312
- * never writes.
493
+ * One write of the destination's session secret — and nothing else — in one
494
+ * `saveSession`, built from the write alone: the store merges, so every
495
+ * field that must not survive from an earlier write is stated.
313
496
  *
314
- * - `expiresAt`: fixed by `onTokens` when the result arrived — the result's
315
- * own, else the `expiresIn` it reports counted from then (the rule the
316
- * provider applies to its own cache).
317
- * - `refreshToken`: the result's, else the one the session holds, read at
318
- * write time, so a result without one does not erase the stored one — for
319
- * a provider the broker built, only a stored one bound where this one is:
320
- * a refresh token obtained for another resource or from another client is
321
- * not carried into this secret. So too for a consumer's factory beside a
322
- * `clientAuthentication` strategy, seeded only with a bound session. A
323
- * consumer's provider without one was seeded with whatever the session
324
- * held, so whatever it holds is carried (4.0.0).
325
- * - `issuedFor` / `issuedBy`: the binding computed when the provider was
326
- * built, each left out when the means lack its source — so the
327
- * store clears it.
497
+ * - A credential: `{ authorizationToken, expiresAt, refreshToken, issuedFor,
498
+ * issuedBy }`, or for `saml2_pure`'s cookies (`tokenType: 'saml'`)
499
+ * `{ sessionCookies, expiresAt, refreshToken: '', issuedFor, issuedBy }` —
500
+ * SAML has no refresh token, and one stored beside earlier cookies or a
501
+ * token is not this credential's.
502
+ * - `refreshToken`: decided when the write was submitted — the build's own,
503
+ * or `''`, the store's clearing operation. The store is never read here.
504
+ * - `issuedFor` / `issuedBy`: the binding fixed when the provider was built,
505
+ * `issuedFor` written as `''` when the means lack its source — never left
506
+ * out, so no earlier binding survives beside a new credential.
507
+ * - A write that holds no credential (a refresh token discarded before any
508
+ * was held) writes only `refreshToken: ''`: the stored credential keeps
509
+ * its own binding — never re-labelled — and loses its refresh token.
510
+ * - `expiresAt`: fixed when the credential arrived.
328
511
  * - A destination the key store now states as `basic` or `snc` is not
329
512
  * written: those obtain no session secret.
330
513
  */
@@ -332,8 +515,9 @@ export declare class AuthBroker {
332
515
  /**
333
516
  * An `ITokenRefresher` for one destination, for injection into a connection:
334
517
  * `getToken()` is the broker's `getToken`, `refreshToken()` its forced
335
- * `refreshToken`.
518
+ * `refreshToken` — each call a waiter with `options.signal`, so a
519
+ * refresher held by a session ends with it.
336
520
  */
337
- createTokenRefresher(destination: string): ITokenRefresher;
521
+ createTokenRefresher(destination: string, options?: BrokerCallOptions): ITokenRefresher;
338
522
  }
339
523
  //# sourceMappingURL=AuthBroker.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AuthBroker.d.ts","sourceRoot":"","sources":["../src/AuthBroker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EACV,oBAAoB,EACpB,kBAAkB,EACnB,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EACV,qBAAqB,EACrB,sBAAsB,EACtB,aAAa,EACb,qBAAqB,EACrB,yBAAyB,EACzB,eAAe,EAEhB,MAAM,+BAA+B,CAAC;AAGvC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAQ9D,OAAO,EACL,KAAK,4BAA4B,EAMlC,MAAM,wBAAwB,CAAC;AAiBhC,OAAO,KAAK,EACV,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACd,MAAM,qBAAqB,CAAC;AAS7B;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,oBAAoB,GAAG,CACjC,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,oBAAoB,GAAG,IAAI,EACvC,UAAU,EAAE,iBAAiB,EAC7B,MAAM,CAAC,EAAE,mBAAmB,KACzB,yBAAyB,CAAC;AAE/B;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,oEAAoE;IACpE,QAAQ,CAAC,oBAAoB,CAAC,EAAE,qBAAqB,CAAC;IACtD;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;;OAKG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,2EAA2E;AAC3E,MAAM,MAAM,aAAa,GACrB,oBAAoB,GACpB,UAAU,GACV,YAAY,GACZ,cAAc,CAAC;AAEnB;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,YAAY,EAAE,aAAa,CAAC;IAC5B;;;;OAIG;IACH,eAAe,CAAC,EAAE,gBAAgB,CAAC;IACnC;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,yBAAyB,GAAG,oBAAoB,CAAC;IAM5D,0EAA0E;IAC1E,aAAa,CAAC,EAAE,CACd,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,aAAa,KACjB,sBAAsB,CAAC,MAAM,CAAC,CAAC;IACpC,qEAAqE;IACrE,iBAAiB,CAAC,EAAE,CAClB,WAAW,EAAE,MAAM,KAChB,sBAAsB,CAAC,kBAAkB,CAAC,CAAC;IAChD,qDAAqD;IACrD,mBAAmB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,oBAAoB,CAAC;IACpE,8EAA8E;IAC9E,WAAW,CAAC,EAAE,CACZ,WAAW,EAAE,MAAM,KAChB,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/C,4DAA4D;IAC5D,oBAAoB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,qBAAqB,CAAC;IACtE;;;;;;;;;;;;;;;;;;OAkBG;IACH,oBAAoB,CAAC,EAAE,4BAA4B,CAAC;CACrD;AA4LD;;GAEG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;IACjC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA+B;IAC/D,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAgB;IAC7C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAGX;IACd,4EAA4E;IAC5E,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA6C;IAC3E;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA6C;IACnE;;;;;;OAMG;IACH,OAAO,CAAC,QAAQ,CAAC,YAAY,CAGzB;IACJ,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAoC;IAClE,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAwC;IAC1E,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAA0C;IAC9E,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAkC;IAC9D,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAA2C;IAChF,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAA2C;IAChF,wEAAwE;IACxE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA6B;IAEpD;;;OAGG;gBACS,MAAM,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,OAAO;IAoFtD;;;;;;;;;;;;;;;;;OAiBG;IACG,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIpD;;;;OAIG;IACG,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YAI1C,MAAM;IAWpB;;;;;;OAMG;YACW,eAAe;IAoB7B,iDAAiD;YACnC,YAAY;IAqC1B;;;;;OAKG;YACW,kBAAkB;IA8BhC,wFAAwF;IACxF,OAAO,CAAC,gBAAgB;IAOxB;;;;;;;OAOG;IACH,OAAO,CAAC,mBAAmB;IA8G3B;;;;;;;;;;;;;OAaG;YACW,4BAA4B;IA4C1C;;;;;OAKG;YACW,iBAAiB;IAqB/B,gEAAgE;IAChE,OAAO,CAAC,iBAAiB;IAMzB;;;OAGG;YACW,iBAAiB;IAuB/B;;;;;;;;;;OAUG;YACW,IAAI;IAgBlB;;;;;OAKG;IACG,sBAAsB,CAC1B,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IAwBvC;;;;;;OAMG;IACG,mBAAmB,CACvB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAyBpC;;;;;;;;;;;;;;;;OAgBG;IACH,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;YAiB1C,KAAK;IAmJnB;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB;IAkBxB;;;;;OAKG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAItB;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;YACW,WAAW;IAmDzB;;;;OAIG;IACH,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,eAAe;CAM3D"}
1
+ {"version":3,"file":"AuthBroker.d.ts","sourceRoot":"","sources":["../src/AuthBroker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAUH,OAAO,KAAK,EACV,oBAAoB,EACpB,kBAAkB,EAEnB,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EACV,qBAAqB,EACrB,sBAAsB,EACtB,aAAa,EACb,qBAAqB,EACrB,yBAAyB,EACzB,eAAe,EAEhB,MAAM,+BAA+B,CAAC;AAMvC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAe9D,OAAO,EACL,KAAK,4BAA4B,EAMlC,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EAWL,KAAK,aAAa,EAWnB,MAAM,gBAAgB,CAAC;AAcxB,OAAO,KAAK,EACV,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACd,MAAM,qBAAqB,CAAC;AAE7B,4EAA4E;AAC5E,MAAM,WAAW,iBAAiB;IAChC;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;CAC3C;AAuED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,MAAM,oBAAoB,GAAG,CACjC,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,oBAAoB,GAAG,IAAI,EACvC,UAAU,EAAE,iBAAiB,EAC7B,MAAM,CAAC,EAAE,mBAAmB,KACzB,yBAAyB,CAAC;AAE/B;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,oEAAoE;IACpE,QAAQ,CAAC,oBAAoB,CAAC,EAAE,qBAAqB,CAAC;IACtD;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,2EAA2E;AAC3E,MAAM,MAAM,aAAa,GACrB,oBAAoB,GACpB,UAAU,GACV,YAAY,GACZ,cAAc,CAAC;AAEnB;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,YAAY,EAAE,aAAa,CAAC;IAC5B;;;;OAIG;IACH,eAAe,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC;IAC/C;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,yBAAyB,GAAG,oBAAoB,GAAG,SAAS,CAAC;IAOxE,0EAA0E;IAC1E,aAAa,CAAC,EACV,CAAC,CACC,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,aAAa,KACjB,sBAAsB,CAAC,MAAM,CAAC,CAAC,GACpC,SAAS,CAAC;IACd,qEAAqE;IACrE,iBAAiB,CAAC,EACd,CAAC,CAAC,WAAW,EAAE,MAAM,KAAK,sBAAsB,CAAC,kBAAkB,CAAC,CAAC,GACrE,SAAS,CAAC;IACd,qDAAqD;IACrD,mBAAmB,CAAC,EAChB,CAAC,CAAC,WAAW,EAAE,MAAM,KAAK,oBAAoB,CAAC,GAC/C,SAAS,CAAC;IACd,8EAA8E;IAC9E,WAAW,CAAC,EACR,CAAC,CAAC,WAAW,EAAE,MAAM,KAAK,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC,GACpE,SAAS,CAAC;IACd,4DAA4D;IAC5D,oBAAoB,CAAC,EACjB,CAAC,CAAC,WAAW,EAAE,MAAM,KAAK,qBAAqB,CAAC,GAChD,SAAS,CAAC;IACd;;;;;;;;;;;;;;;;;;;OAmBG;IACH,oBAAoB,CAAC,EAAE,4BAA4B,GAAG,SAAS,CAAC;IAChE;;;;;;;;;OASG;IACH,OAAO,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IACpC;;;;;;;;;;;OAWG;IACH,cAAc,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;IACjD;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACjC;AAmQD;;GAEG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;IACjC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA+B;IAC/D,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAgB;IAC7C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAGX;IACd,wEAAwE;IACxE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAkC;IAC9D,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAuC;IACxE;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAGrB;IACJ,OAAO,CAAC,QAAQ,CAAC,aAAa,CAG1B;IACJ,yDAAyD;IACzD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAC8B;IACxD,iEAAiE;IACjE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;IACjD,0EAA0E;IAC1E,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAqB;IAClD;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAqB;IACrD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAoC;IAClE,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAwC;IAC1E,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAA0C;IAC9E,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAkC;IAC9D,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAA2C;IAChF,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAA2C;IAChF,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA8B;IACtD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAqC;IACpE,gFAAgF;IAChF,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAU;IACpC,0EAA0E;IAC1E,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA6B;IAEpD;;;OAGG;gBACS,MAAM,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,OAAO;IA6EtD;;;;;;;;;;;;;;;;;;;;;OAqBG;IACG,QAAQ,CACZ,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,MAAM,CAAC;IAIlB;;;;OAIG;IACG,YAAY,CAChB,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,MAAM,CAAC;IAIlB;;;;;OAKG;YACW,MAAM;IAiCpB;;;;;;;;;;;;;;OAcG;YACW,aAAa;IAa3B;;;;;;OAMG;YACW,eAAe;IAkB7B;;;OAGG;YACW,YAAY;IAyC1B;;;;;OAKG;YACW,kBAAkB;IAuChC;;;;;OAKG;IACH,OAAO,CAAC,MAAM;IAYd,2EAA2E;IAC3E,OAAO,CAAC,SAAS;IAIjB,+DAA+D;IAC/D,OAAO,CAAC,cAAc;IAMtB;;;;;;;OAOG;YACW,MAAM;IAoBpB,8DAA8D;IAC9D,OAAO,CAAC,UAAU;IA0ClB;;;;;;OAMG;IACH,OAAO,CAAC,eAAe;IAgDvB;;;;;;;OAOG;YACW,aAAa;IAqE3B;;;;;;;;;;;;;OAaG;YACW,4BAA4B;IAyC1C;;;;;;OAMG;YACW,iBAAiB;IAe/B;;;;;;OAMG;YACW,cAAc;IAuB5B;;;OAGG;IACH,OAAO,CAAC,YAAY;IAepB;;;;;;;;;;OAUG;YACW,IAAI;IAgBlB;;;;;OAKG;IACG,sBAAsB,CAC1B,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IAwBvC;;;;;;OAMG;IACG,mBAAmB,CACvB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAyBpC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+BG;IACG,WAAW,CACf,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,aAAa,CAAC;IAezB;;;;OAIG;IACH,OAAO,CAAC,UAAU;IAgDlB;;;;;;;OAOG;YACW,KAAK;IAgNnB;;;;;;OAMG;IACH,OAAO,CAAC,UAAU;IA6ClB;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,gBAAgB;IAwBxB;;;;;;;;;;;;OAYG;IACH,KAAK,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjD;;;;;;;;;;;;;;;;;;;;;OAqBG;YACW,WAAW;IA2CzB;;;;;OAKG;IACH,oBAAoB,CAClB,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,eAAe;CAOnB"}