@mcp-abap-adt/auth-broker 4.0.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
@@ -19,22 +26,72 @@
19
26
  * broker does not repeat or override any of them.
20
27
  */
21
28
  import type { IDeviceCodePresenter, OidcCallbackResult } from '@mcp-abap-adt/auth-providers';
22
- import type { IAssertionReplayStore, IAuthorizationStrategy, IAuthProvider, IRefreshableTokenProvider, ITokenRefresher } from '@mcp-abap-adt/interfaces-auth';
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';
31
+ import { type ClientAuthenticationStrategy } from './clientAuthentication';
32
+ import { type RenewalOption } from './destinations';
24
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
+ }
25
44
  /**
26
- * 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.
27
49
  *
28
- * - `authConfig`: the UAA credentials — from the session when it holds them,
29
- * else from the service key — with the refresh token the session stored, or
30
- * `null` when neither store has credentials (a SAML flow needs none).
31
- * - `connConfig`: the session's connection config, with `serviceUrl` resolved
32
- * and the last token the session stored, so the provider can reuse it while
33
- * it is valid.
50
+ * It is handed exactly these, and nothing else a store answered:
34
51
  *
35
- * Called once per destination; the broker keeps the provider it returns.
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.
66
+ *
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.
71
+ */
72
+ export type TokenProviderFactory = (destination: string, authConfig: IAuthorizationConfig | null, connConfig: IConnectionConfig, client?: TokenProviderClient) => IRefreshableTokenProvider;
73
+ /**
74
+ * The token API factory's fourth argument — present only when the broker was
75
+ * given a `clientAuthentication` strategy and the destination states a grant
76
+ * whose client authenticates; without one the factory is called with three
77
+ * arguments, as 4.0.0. It never carries a certificate, a key or a secret.
36
78
  */
37
- export type TokenProviderFactory = (destination: string, authConfig: IAuthorizationConfig | null, connConfig: IConnectionConfig) => IRefreshableTokenProvider;
79
+ export interface TokenProviderClient {
80
+ /** The strategy's answer, resolved before the factory is called. */
81
+ readonly clientAuthentication?: IClientAuthentication;
82
+ /**
83
+ * The client's identity — the secret client's `uaaUrl` when the stores hold
84
+ * one, else the certificate client's; absent when there is neither.
85
+ */
86
+ readonly uaaUrl?: string;
87
+ /** The client id beside `uaaUrl`, from the same client. */
88
+ readonly clientId?: string;
89
+ /**
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.
92
+ */
93
+ readonly refreshToken?: string;
94
+ }
38
95
  /** The grants whose provider takes an `IAuthorizationStrategy<string>`. */
39
96
  export type StrategyGrant = 'authorization_code' | 'passcode' | 'saml2_pure' | 'saml2_bearer';
40
97
  /**
@@ -51,26 +108,82 @@ export interface AuthBrokerConfig {
51
108
  * basic's user and password, the SNC fields, `serviceUrl`. `getProvider`
52
109
  * needs it: there is no other source of means.
53
110
  */
54
- serviceKeyStore?: IServiceKeyStore;
111
+ serviceKeyStore?: IServiceKeyStore | undefined;
55
112
  /**
56
113
  * The token API's source: the token provider, or a factory building one per
57
114
  * destination. Not used by `getProvider`, which builds what the destination
58
115
  * states.
59
116
  *
60
- * An instance is used as given, for every destination. A factory is seeded
61
- * 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`).
62
120
  */
63
- provider?: IRefreshableTokenProvider | TokenProviderFactory;
121
+ provider?: IRefreshableTokenProvider | TokenProviderFactory | undefined;
64
122
  /** The interactive strategy of the UAA code, passcode and SAML grants. */
65
- authorization?: (destination: string, grant: StrategyGrant) => IAuthorizationStrategy<string>;
123
+ authorization?: ((destination: string, grant: StrategyGrant) => IAuthorizationStrategy<string>) | undefined;
66
124
  /** The interactive strategy of the OIDC authorization code grant. */
67
- oidcAuthorization?: (destination: string) => IAuthorizationStrategy<OidcCallbackResult>;
125
+ oidcAuthorization?: ((destination: string) => IAuthorizationStrategy<OidcCallbackResult>) | undefined;
68
126
  /** Where the device flow shows the user its code. */
69
- deviceCodePresenter?: (destination: string) => IDeviceCodePresenter;
127
+ deviceCodePresenter?: ((destination: string) => IDeviceCodePresenter) | undefined;
70
128
  /** `saml2_pure`: turns the SAMLResponse into the system's session cookies. */
71
- samlCookies?: (destination: string) => (samlResponse: string) => Promise<string>;
129
+ samlCookies?: ((destination: string) => (samlResponse: string) => Promise<string>) | undefined;
72
130
  /** The replay store the SAML assertion validators share. */
73
- assertionReplayStore?: (destination: string) => IAssertionReplayStore;
131
+ assertionReplayStore?: ((destination: string) => IAssertionReplayStore) | undefined;
132
+ /**
133
+ * How a destination's client authenticates to the authorization server, for
134
+ * every grant that authenticates one (`ClientAuthenticationGrant`). Called
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.
138
+ *
139
+ * A given strategy always answers one, or throws: there is no "nothing"
140
+ * answer, so an explicit choice never falls back to the secret. A throw
141
+ * becomes a `DestinationConfigError` naming `clientAuthentication`, in fixed
142
+ * words. Absent: the client secret, as in 4.0.0, and nothing
143
+ * certificate-related is read. Shipped: `fromServiceKeyCertificate()`,
144
+ * `fromServiceKeySecret({ encoding })`.
145
+ *
146
+ * It applies to the providers the broker builds: `getProvider`'s, and the
147
+ * token API's `provider` factory, which gets its answer as a fourth
148
+ * argument (`TokenProviderClient`) for a grant that authenticates a client.
149
+ * An instance given as `provider` is already composed by the consumer, so
150
+ * the token API uses it as given and calls no strategy for it.
151
+ */
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;
74
187
  }
75
188
  /**
76
189
  * AuthBroker manages authentication tokens for destinations
@@ -80,28 +193,37 @@ export declare class AuthBroker {
80
193
  private readonly serviceKeyStore;
81
194
  private readonly sessionStore;
82
195
  private readonly provider;
83
- /** A consumer factory's providers: the promise of the build, as `built`. */
84
- private readonly consumerBuilt;
196
+ /** Per (destination, path): the provider handed out while unchanged. */
197
+ private readonly resolvedRow;
198
+ private readonly resolvedConsumer;
85
199
  /**
86
- * One cache per destination, shared by `getProvider` and — when the
87
- * consumer gives no provider — the token API: the promise of the
88
- * 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.
89
202
  */
90
- 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;
91
211
  /**
92
- * The write that failed for a result, keyed on the result the provider
93
- * handed over and returns, then on the destination it was written
94
- * for: the token API throws it to its caller, as 3.x did, while the broker
95
- * keeps retrying. Dropped once a write of that result for that destination
96
- * lands.
212
+ * The destinations whose means changed under the consumer's instance: the
213
+ * token API refuses them until a new broker.
97
214
  */
98
- private readonly failedWrites;
215
+ private readonly instanceRefused;
99
216
  private readonly authorization;
100
217
  private readonly oidcAuthorization;
101
218
  private readonly deviceCodePresenter;
102
219
  private readonly samlCookies;
103
220
  private readonly assertionReplayStore;
104
- /** getProvider's writes of the session secret, retried on their own. */
221
+ private readonly clientAuthentication;
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. */
105
227
  private readonly writer;
106
228
  /**
107
229
  * @param config Stores and the provider (instance or factory)
@@ -114,26 +236,52 @@ export declare class AuthBroker {
114
236
  *
115
237
  * Without a consumer `provider`, the provider is the one `getProvider` hands
116
238
  * out for the destination — the same instance, so one token and one renewal
117
- * 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,
118
240
  * the consumer's provider is asked and its answer written, as in 3.x — the
119
241
  * secret alone.
120
242
  *
121
- * Errors from the provider (its typed errors included) propagate unchanged;
122
- * so does a store failure, a failed write of the token included — the token
123
- * 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'`.
124
249
  *
125
250
  * @throws DestinationConfigError for a destination the key store states as
126
- * `basic` or `snc`, before any provider is asked; without a consumer
127
- * `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.
128
254
  */
129
- getToken(destination: string): Promise<string>;
255
+ getToken(destination: string, options?: BrokerCallOptions): Promise<string>;
130
256
  /**
131
257
  * A new token for the destination, never the cached one — for a caller whose
132
258
  * token the server has just refused. Calls the provider's `refreshTokens()`;
133
259
  * a renewal already in flight for the destination is joined, not repeated.
134
260
  */
135
- 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
+ */
136
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;
137
285
  /**
138
286
  * The destination's means, read first: a destination the key store states
139
287
  * as `basic` or `snc` holds no token, so the token API refuses it before any
@@ -142,38 +290,93 @@ export declare class AuthBroker {
142
290
  * a 3.x setup, served as before.
143
291
  */
144
292
  private statedForTokens;
145
- /** 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
+ */
146
297
  private obtainShared;
147
298
  /**
148
- * The token API on the consumer's provider, as 3.x: the session read first,
149
- * then the key store, for `serviceUrl` and the client; every answer — a
150
- * cache hit included — written, the secret alone, through the broker's one
151
- * 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.
152
303
  */
153
304
  private obtainFromConsumer;
154
- /** The failure recorded for this result's write here, thrown as the store raised it. */
155
- private throwFailedWrite;
156
305
  /**
157
- * The consumer's provider for the destination, cached per destination as a
158
- * promise set before its first read and dropped when it throws, so
159
- * the next call builds again: a factory's build — handed the client resolved
160
- * then — or an instance as given, for every destination, handed no client.
161
- * Either way the binding is fixed here, from the `serviceUrl`, SAP client and
162
- * 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.
310
+ */
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;
344
+ /**
345
+ * The token API's strategy path: with a `clientAuthentication` strategy and a
346
+ * destination stating a grant whose client authenticates, the strategy's
347
+ * answer — resolved inside the guard — and the client identity: the secret
348
+ * client, else the certificate client's, read through the context's memoised
349
+ * `readCertificate`. `null` without a strategy (4.0.0: nothing
350
+ * certificate-related is asked) and for a grant that authenticates no
351
+ * client (`saml2_pure`, `none`), as `getProvider` decides.
352
+ *
353
+ * The strategy is told the grant, so a destination that states none is
354
+ * refused before it is called rather than built without it. (An instance
355
+ * given as `provider` is the consumer's own composition: the strategy
356
+ * applies only to what the broker builds, so it is not used there.)
163
357
  */
164
- private consumerProviderFor;
358
+ private consumerClientAuthentication;
165
359
  /**
166
- * The credentials a consumer's factory is built with: the session's own when
167
- * it holds them, else the service key's, carrying the refresh token the
168
- * session stored — the 3.x order. A session store of auth-stores 3
360
+ * What a consumer's factory's credentials are composed from, read in the
361
+ * 3.x order: the session's authorization config; only when it has none, the
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
169
364
  * answers no client, so the key store's is what is found.
170
365
  */
171
- private resolveAuthorizationConfig;
366
+ private readAuthorization;
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;
172
375
  /**
173
376
  * `serviceUrl` for a consumer's provider, in the 3.x order: the session's,
174
377
  * else the key store's, else an error before the provider is asked.
175
378
  */
176
- private resolveServiceUrl;
379
+ private serviceUrlOf;
177
380
  /**
178
381
  * A store read where absence is an answer and anything else is not.
179
382
  *
@@ -207,54 +410,104 @@ export declare class AuthBroker {
207
410
  * built from the means the service key store holds and the secret the
208
411
  * session store holds.
209
412
  *
210
- * One provider per destination for the broker's life: concurrent first calls
211
- * 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.
212
423
  *
213
424
  * A token provider (the UAA, OIDC and SAML grants) is seeded from the
214
- * session when the stored secret is bound to this destination, and writes
215
- * every token it obtains — at `prepare()`, on expiry, or in `rejected()` after
216
- * 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.
217
435
  *
218
436
  * @throws DestinationConfigError when the destination lacks what its type
219
437
  * needs — naming the fields or options, never a value.
220
438
  */
221
- 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
+ */
222
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;
223
463
  /**
224
464
  * The stored secret when it is bound to this destination's resource and
225
465
  * issuer, else `null`: the provider is then built as with no session
226
- * and logs in afresh — the refresh token is not spent either. The log line
227
- * 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.
228
476
  */
229
477
  private boundOrDiscarded;
230
478
  /**
231
- * Waits for the session writes still pending — each gets one more attempt —
232
- * and rejects naming the destinations whose store still refuses. Call it on
233
- * shutdown to know whether every token a provider obtained is stored; the
234
- * 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.
235
490
  */
236
- flush(): Promise<void>;
491
+ flush(options?: BrokerCallOptions): Promise<void>;
237
492
  /**
238
- * One write of the destination's session secret — and nothing else:
239
- * `{ authorizationToken, expiresAt, refreshToken, issuedFor, issuedBy }` in
240
- * one `saveSession` — or, for a `saml2_pure` result (`tokenType: 'saml'`),
241
- * `{ sessionCookies, expiresAt, issuedFor, issuedBy }`: cookies are written
242
- * as cookies, every other result as a token (`saml2_bearer` included). No means is ever written: not `serviceUrl`, not
243
- * `authType`, not the client — they live in the key store, which the broker
244
- * 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.
245
496
  *
246
- * - `expiresAt`: fixed by `onTokens` when the result arrived — the result's
247
- * own, else the `expiresIn` it reports counted from then (the rule the
248
- * provider applies to its own cache).
249
- * - `refreshToken`: the result's, else the one the session holds, read at
250
- * write time, so a result without one does not erase the stored one — for
251
- * a provider the broker built, only a stored one bound where this one is:
252
- * a refresh token obtained for another resource or from another client is
253
- * not carried into this secret. A consumer's provider was seeded
254
- * with whatever the session held, so whatever it holds is carried.
255
- * - `issuedFor` / `issuedBy`: the binding computed when the provider was
256
- * built, each left out when the means lack its source — so the
257
- * 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.
258
511
  * - A destination the key store now states as `basic` or `snc` is not
259
512
  * written: those obtain no session secret.
260
513
  */
@@ -262,8 +515,9 @@ export declare class AuthBroker {
262
515
  /**
263
516
  * An `ITokenRefresher` for one destination, for injection into a connection:
264
517
  * `getToken()` is the broker's `getToken`, `refreshToken()` its forced
265
- * `refreshToken`.
518
+ * `refreshToken` — each call a waiter with `options.signal`, so a
519
+ * refresher held by a session ends with it.
266
520
  */
267
- createTokenRefresher(destination: string): ITokenRefresher;
521
+ createTokenRefresher(destination: string, options?: BrokerCallOptions): ITokenRefresher;
268
522
  }
269
523
  //# sourceMappingURL=AuthBroker.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AuthBroker.d.ts","sourceRoot":"","sources":["../src/AuthBroker.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AuthBroker.d.ts","sourceRoot":"","sources":["../src/AuthBroker.ts"],"names":[],"mappings":"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"}