@exortek/apikey 1.1.1 → 1.1.3
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.
- package/CHANGELOG.md +32 -0
- package/README.md +3 -3
- package/dist/index.cjs +37 -291
- package/dist/index.d.ts +145 -18
- package/dist/index.mjs +37 -291
- package/dist/internal/guards.d.ts +2 -2
- package/dist/middleware/express.cjs +38 -292
- package/dist/middleware/express.d.ts +96 -1
- package/dist/middleware/express.mjs +38 -292
- package/dist/middleware/fastify.cjs +38 -292
- package/dist/middleware/fastify.d.ts +3 -1
- package/dist/middleware/fastify.mjs +38 -292
- package/dist/stores/custom.d.ts +1 -8
- package/dist/stores/index.d.ts +79 -3
- package/dist/stores.cjs +164 -317
- package/dist/stores.mjs +164 -317
- package/dist/token.d.ts +2 -1
- package/package.json +5 -5
|
@@ -137,20 +137,33 @@ function isBuffer(value) {
|
|
|
137
137
|
* `@exortek/shared/validate`: **schema** for whole options objects,
|
|
138
138
|
* **asserts** for one-liner argument guards at the call site.
|
|
139
139
|
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
*
|
|
140
|
+
* Every guard is exported as a `make…` **factory** taking the binding
|
|
141
|
+
* package's `wrap` and returning the guard itself. A package binds the
|
|
142
|
+
* guards it calls once, in its `internal/guards.js`, so every argument
|
|
143
|
+
* failure throws that package's error class — `err instanceof
|
|
144
|
+
* CryptoError` holds, and users see at a glance which package raised it.
|
|
145
|
+
*
|
|
146
|
+
* // packages/<pkg>/src/internal/guards.js
|
|
147
|
+
* import { makeAssertString, makeInvalidArgument } from '@exortek/shared/asserts';
|
|
148
|
+
* import { CryptoError, ErrorCode } from '../errors.js';
|
|
149
|
+
*
|
|
150
|
+
* const wrap = (message, extra) => new CryptoError(ErrorCode.INVALID_ARGUMENT, message, extra);
|
|
151
|
+
*
|
|
152
|
+
* export const assertString = makeAssertString(wrap);
|
|
153
|
+
* export const invalidArgument = makeInvalidArgument(wrap);
|
|
154
|
+
*
|
|
155
|
+
* Importing each factory by name is what makes the module
|
|
156
|
+
* tree-shakeable. An earlier version handed back one object carrying
|
|
157
|
+
* every guard, so all of them shipped in every package's bundle no
|
|
158
|
+
* matter how few were used — `assertBoolean` reached fifteen published
|
|
159
|
+
* packages without a single call site. Import what you call.
|
|
147
160
|
*
|
|
148
161
|
* **Path naming convention** (used as the `name` argument):
|
|
149
162
|
*
|
|
150
163
|
* `<publicFunction>[.options|.config][.<field>]`
|
|
151
164
|
*
|
|
152
|
-
* - `assertString(name, 'createUser.name')`
|
|
153
|
-
* - `assertPositiveInt(n, 'scrypt.options.r')`
|
|
165
|
+
* - `assertString(name, 'createUser.name')` — top-level arg
|
|
166
|
+
* - `assertPositiveInt(n, 'scrypt.options.r')` — nested option
|
|
154
167
|
* - `assertBytesOrString(pwd, 'pepper.wrap.password')` — method arg
|
|
155
168
|
*
|
|
156
169
|
* Keep the path short: the emitted error is `"<name> must be <desc>"`,
|
|
@@ -159,289 +172,17 @@ function isBuffer(value) {
|
|
|
159
172
|
* encryptSymmetric()"), not for restating the field.
|
|
160
173
|
*/
|
|
161
174
|
|
|
162
|
-
/**
|
|
163
|
-
* @typedef {{ cause?: unknown }} WrapExtra
|
|
164
|
-
* Extra options forwarded to the wrap function, so `invalidArgument`
|
|
165
|
-
* sites that catch an underlying error can preserve the `cause` chain
|
|
166
|
-
* without falling back to a raw `new PackageError(...)`.
|
|
167
|
-
*
|
|
168
|
-
* @typedef {(message: string, extra?: WrapExtra) => Error} WrapFn
|
|
169
|
-
* Constructs (never throws) the binding package's error, e.g.
|
|
170
|
-
* `(m, { cause } = {}) => new CryptoError(ErrorCode.INVALID_ARGUMENT, m, { cause })`.
|
|
171
|
-
*
|
|
172
|
-
* @typedef {{ hint?: string }} AssertOptions
|
|
173
|
-
* `hint` is appended to the message after an em-dash — use it for
|
|
174
|
-
* actionable guidance ("pass the exact bytes returned by …").
|
|
175
|
-
*
|
|
176
|
-
* @typedef {{ safeParse: (input: unknown, path?: string) => { ok: true, value: unknown } | { ok: false, errors: string[] } }} ParseableSchema
|
|
177
|
-
*/
|
|
178
175
|
|
|
179
176
|
/**
|
|
180
|
-
*
|
|
181
|
-
* `
|
|
182
|
-
*
|
|
177
|
+
* Construct (not throw) the bound error with a free-form message — for
|
|
178
|
+
* `throw invalidArgument('…')` sites that don't fit the `X must be Y`
|
|
179
|
+
* shape (canonicalisation errors, cross-field constraint failures). Pass
|
|
180
|
+
* `{ cause }` when the failure was triggered by an underlying throw whose
|
|
181
|
+
* chain matters (e.g. `JSON.stringify` on a bigint).
|
|
183
182
|
*
|
|
184
|
-
* @
|
|
185
|
-
* @param {string} description
|
|
186
|
-
* @param {string} [hint]
|
|
187
|
-
* @returns {string}
|
|
183
|
+
* @type {(wrap: WrapFn) => (msg: string, extra?: WrapExtra) => Error}
|
|
188
184
|
*/
|
|
189
|
-
|
|
190
|
-
return `${name} must be ${description}${hint ? ` — ${hint}` : ''}`;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
const ENCODINGS = new Set(['hex', 'base64', 'base64url']);
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* Bind the assert set to a package's error class. Call once per
|
|
197
|
-
* package (conventionally in `internal/guards.js`) and import the
|
|
198
|
-
* bound object everywhere:
|
|
199
|
-
*
|
|
200
|
-
* import { bindAsserts } from '@exortek/shared/asserts';
|
|
201
|
-
* import { CryptoError, ErrorCode } from '../errors.js';
|
|
202
|
-
* export const g = bindAsserts((m) => new CryptoError(ErrorCode.INVALID_ARGUMENT, m));
|
|
203
|
-
*
|
|
204
|
-
* // call sites:
|
|
205
|
-
* g.assertPositiveInt(options.iterations, 'options.iterations');
|
|
206
|
-
* const cfg = g.parse(OptionsSchema, options, 'options');
|
|
207
|
-
*
|
|
208
|
-
* @param {WrapFn} wrap
|
|
209
|
-
*/
|
|
210
|
-
function bindAsserts(wrap) {
|
|
211
|
-
/**
|
|
212
|
-
* @param {string} name
|
|
213
|
-
* @param {string} description
|
|
214
|
-
* @param {AssertOptions} [opts]
|
|
215
|
-
* @returns {never}
|
|
216
|
-
*/
|
|
217
|
-
function fail(name, description, opts) {
|
|
218
|
-
throw wrap(message(name, description, opts?.hint));
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
/**
|
|
222
|
-
* Assert that `value` is a plain object (not `null`, not an array,
|
|
223
|
-
* not a primitive).
|
|
224
|
-
* @param {unknown} value
|
|
225
|
-
* @param {string} name
|
|
226
|
-
* @param {AssertOptions} [opts]
|
|
227
|
-
*/
|
|
228
|
-
function assertObject(value, name, opts) {
|
|
229
|
-
if (value === null || typeof value !== 'object' || Array.isArray(value)) {
|
|
230
|
-
fail(name, 'an object', opts);
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
return {
|
|
235
|
-
/**
|
|
236
|
-
* Construct (not throw) the bound error with a free-form message —
|
|
237
|
-
* for `throw g.invalidArgument('…')` sites that don't fit the
|
|
238
|
-
* `X must be Y` shape (canonicalisation errors, cross-field
|
|
239
|
-
* constraint failures). Pass `{ cause }` when the argument-shape
|
|
240
|
-
* failure was triggered by an underlying throw whose chain matters
|
|
241
|
-
* (e.g. `JSON.stringify` on a bigint).
|
|
242
|
-
*
|
|
243
|
-
* @param {string} msg
|
|
244
|
-
* @param {WrapExtra} [extra]
|
|
245
|
-
* @returns {Error}
|
|
246
|
-
*/
|
|
247
|
-
invalidArgument(msg, extra) {
|
|
248
|
-
return wrap(msg, extra);
|
|
249
|
-
},
|
|
250
|
-
|
|
251
|
-
/**
|
|
252
|
-
* Validate `input` against a `@exortek/shared/validate` schema;
|
|
253
|
-
* failures throw the bound error carrying every collected message.
|
|
254
|
-
* The bridge that keeps schema validation on the package's own
|
|
255
|
-
* error surface.
|
|
256
|
-
*
|
|
257
|
-
* @param {ParseableSchema} schema
|
|
258
|
-
* @param {unknown} input
|
|
259
|
-
* @param {string} [path='options']
|
|
260
|
-
* @returns {unknown} the parsed (possibly defaulted) value
|
|
261
|
-
*/
|
|
262
|
-
parse(schema, input, path = 'options') {
|
|
263
|
-
const r = schema.safeParse(input, path);
|
|
264
|
-
if (!r.ok) {
|
|
265
|
-
throw wrap(r.errors.join('; '));
|
|
266
|
-
}
|
|
267
|
-
return r.value;
|
|
268
|
-
},
|
|
269
|
-
|
|
270
|
-
/**
|
|
271
|
-
* Assert that `value` is a non-negative safe integer (`0, 1, 2, …`).
|
|
272
|
-
* @param {unknown} value
|
|
273
|
-
* @param {string} name Argument name to include in the error message.
|
|
274
|
-
* @param {AssertOptions} [opts]
|
|
275
|
-
*/
|
|
276
|
-
assertNonNegativeInt(value, name, opts) {
|
|
277
|
-
if (!Number.isSafeInteger(value) || /** @type {number} */ (value) < 0) {
|
|
278
|
-
fail(name, 'a non-negative safe integer', opts);
|
|
279
|
-
}
|
|
280
|
-
},
|
|
281
|
-
|
|
282
|
-
/**
|
|
283
|
-
* Assert that `value` is a strictly positive safe integer (`1, 2, 3, …`).
|
|
284
|
-
* @param {unknown} value
|
|
285
|
-
* @param {string} name
|
|
286
|
-
* @param {AssertOptions} [opts]
|
|
287
|
-
*/
|
|
288
|
-
assertPositiveInt(value, name, opts) {
|
|
289
|
-
if (!Number.isSafeInteger(value) || /** @type {number} */ (value) <= 0) {
|
|
290
|
-
fail(name, 'a positive integer', opts);
|
|
291
|
-
}
|
|
292
|
-
},
|
|
293
|
-
|
|
294
|
-
/**
|
|
295
|
-
* Assert that `value` fits in a 48-bit unsigned integer (`0 … 2^48 − 1`).
|
|
296
|
-
* Used for Unix millisecond timestamps in UUID v7 / ULID.
|
|
297
|
-
* @param {unknown} value
|
|
298
|
-
* @param {string} name
|
|
299
|
-
* @param {AssertOptions} [opts]
|
|
300
|
-
*/
|
|
301
|
-
assertUint48(value, name, opts) {
|
|
302
|
-
if (
|
|
303
|
-
!Number.isSafeInteger(value) ||
|
|
304
|
-
/** @type {number} */ (value) < 0 ||
|
|
305
|
-
/** @type {number} */ (value) > 0xffffffffffff
|
|
306
|
-
) {
|
|
307
|
-
fail(name, 'a non-negative safe integer ≤ 2^48 − 1 (Unix ms since epoch)', opts);
|
|
308
|
-
}
|
|
309
|
-
},
|
|
310
|
-
|
|
311
|
-
/**
|
|
312
|
-
* Assert that `value` is a string (may be empty).
|
|
313
|
-
* @param {unknown} value
|
|
314
|
-
* @param {string} name
|
|
315
|
-
* @param {AssertOptions} [opts]
|
|
316
|
-
*/
|
|
317
|
-
assertString(value, name, opts) {
|
|
318
|
-
if (typeof value !== 'string') {
|
|
319
|
-
fail(name, 'a string', opts);
|
|
320
|
-
}
|
|
321
|
-
},
|
|
322
|
-
|
|
323
|
-
/**
|
|
324
|
-
* Assert that `value` is a non-empty string.
|
|
325
|
-
* @param {unknown} value
|
|
326
|
-
* @param {string} name
|
|
327
|
-
* @param {AssertOptions} [opts]
|
|
328
|
-
*/
|
|
329
|
-
assertNonEmptyString(value, name, opts) {
|
|
330
|
-
if (typeof value !== 'string' || value.length === 0) {
|
|
331
|
-
fail(name, 'a non-empty string', opts);
|
|
332
|
-
}
|
|
333
|
-
},
|
|
334
|
-
|
|
335
|
-
/**
|
|
336
|
-
* Assert that `value` is a boolean.
|
|
337
|
-
* @param {unknown} value
|
|
338
|
-
* @param {string} name
|
|
339
|
-
* @param {AssertOptions} [opts]
|
|
340
|
-
*/
|
|
341
|
-
assertBoolean(value, name, opts) {
|
|
342
|
-
if (typeof value !== 'boolean') {
|
|
343
|
-
fail(name, 'a boolean', opts);
|
|
344
|
-
}
|
|
345
|
-
},
|
|
346
|
-
|
|
347
|
-
/**
|
|
348
|
-
* Assert that `value` is a function.
|
|
349
|
-
* @param {unknown} value
|
|
350
|
-
* @param {string} name
|
|
351
|
-
* @param {AssertOptions} [opts]
|
|
352
|
-
*/
|
|
353
|
-
assertFunction(value, name, opts) {
|
|
354
|
-
if (typeof value !== 'function') {
|
|
355
|
-
fail(name, 'a function', opts);
|
|
356
|
-
}
|
|
357
|
-
},
|
|
358
|
-
|
|
359
|
-
assertObject,
|
|
360
|
-
|
|
361
|
-
/**
|
|
362
|
-
* Assert that `value` is either `undefined` or a plain object —
|
|
363
|
-
* the "optional options object" pattern.
|
|
364
|
-
* @param {unknown} value
|
|
365
|
-
* @param {string} name
|
|
366
|
-
* @param {AssertOptions} [opts]
|
|
367
|
-
*/
|
|
368
|
-
assertOptionalObject(value, name, opts) {
|
|
369
|
-
if (value === undefined) {
|
|
370
|
-
return;
|
|
371
|
-
}
|
|
372
|
-
assertObject(value, name, opts);
|
|
373
|
-
},
|
|
374
|
-
|
|
375
|
-
/**
|
|
376
|
-
* Assert that `value` is a byte buffer (`Buffer` or `Uint8Array`) —
|
|
377
|
-
* strings are NOT accepted. For already-encoded material where a
|
|
378
|
-
* string would be ambiguous (ciphertext, signatures, raw key bytes).
|
|
379
|
-
* @param {unknown} value
|
|
380
|
-
* @param {string} name
|
|
381
|
-
* @param {AssertOptions} [opts]
|
|
382
|
-
*/
|
|
383
|
-
assertBytes(value, name, opts) {
|
|
384
|
-
if (!Buffer.isBuffer(value) && !(value instanceof Uint8Array)) {
|
|
385
|
-
fail(name, 'a Buffer or Uint8Array', opts);
|
|
386
|
-
}
|
|
387
|
-
},
|
|
388
|
-
|
|
389
|
-
/**
|
|
390
|
-
* Assert that `value` is either a string or a byte buffer (`Buffer`
|
|
391
|
-
* or `Uint8Array`).
|
|
392
|
-
* @param {unknown} value
|
|
393
|
-
* @param {string} name
|
|
394
|
-
* @param {AssertOptions} [opts]
|
|
395
|
-
*/
|
|
396
|
-
assertBytesOrString(value, name, opts) {
|
|
397
|
-
if (typeof value !== 'string' && !Buffer.isBuffer(value) && !(value instanceof Uint8Array)) {
|
|
398
|
-
fail(name, 'a string or Buffer', opts);
|
|
399
|
-
}
|
|
400
|
-
},
|
|
401
|
-
|
|
402
|
-
/**
|
|
403
|
-
* Assert that `encoding` is one of the accepted output/input
|
|
404
|
-
* encodings. Pass `allowBuffer: false` where a `Buffer` output makes
|
|
405
|
-
* no sense (verifying a string signature, decoding a token payload).
|
|
406
|
-
*
|
|
407
|
-
* @param {unknown} encoding
|
|
408
|
-
* @param {string} name
|
|
409
|
-
* @param {AssertOptions & { allowBuffer?: boolean }} [opts]
|
|
410
|
-
*/
|
|
411
|
-
assertEncoding(encoding, name, opts) {
|
|
412
|
-
const allowBuffer = opts?.allowBuffer !== false;
|
|
413
|
-
const valid = (typeof encoding === 'string' && ENCODINGS.has(encoding)) || (allowBuffer && encoding === 'buffer');
|
|
414
|
-
if (!valid) {
|
|
415
|
-
const list = allowBuffer ? "'hex', 'base64', 'base64url', or 'buffer'" : "'hex', 'base64', or 'base64url'";
|
|
416
|
-
fail(name, list, opts);
|
|
417
|
-
}
|
|
418
|
-
},
|
|
419
|
-
};
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
/**
|
|
423
|
-
* One-line sugar over {@link bindAsserts} — the overwhelmingly common
|
|
424
|
-
* pattern where a package binds every argument-shape failure to its
|
|
425
|
-
* own error class + `INVALID_ARGUMENT` code. Emits the standard
|
|
426
|
-
* `new ErrorClass(code, message, { cause })` shape, so the underlying
|
|
427
|
-
* `BaseError` `{ cause, status, details }` options object is respected.
|
|
428
|
-
*
|
|
429
|
-
* // packages/<pkg>/src/internal/guards.js
|
|
430
|
-
* import { defineGuards } from '@exortek/shared/asserts';
|
|
431
|
-
* import { PasswordError, ErrorCode } from '../errors.js';
|
|
432
|
-
*
|
|
433
|
-
* export const { assertString, invalidArgument, parse } =
|
|
434
|
-
* defineGuards(PasswordError, ErrorCode.INVALID_ARGUMENT);
|
|
435
|
-
*
|
|
436
|
-
* Reach for the raw {@link bindAsserts} when you need a different
|
|
437
|
-
* mapping (an alt code, a decorated message) — it stays available.
|
|
438
|
-
*
|
|
439
|
-
* @param {new (code: string, message: string, options?: { cause?: unknown }) => Error} ErrorClass
|
|
440
|
-
* @param {string} code
|
|
441
|
-
*/
|
|
442
|
-
function defineGuards(ErrorClass, code) {
|
|
443
|
-
return bindAsserts((message, extra) => new ErrorClass(code, message, extra));
|
|
444
|
-
}
|
|
185
|
+
const makeInvalidArgument = wrap => (msg, extra) => wrap(msg, extra);
|
|
445
186
|
|
|
446
187
|
/**
|
|
447
188
|
* Shared base error class — the single error structure behind every
|
|
@@ -552,10 +293,15 @@ class ApiKeyError extends BaseError {
|
|
|
552
293
|
*/
|
|
553
294
|
|
|
554
295
|
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
296
|
+
/**
|
|
297
|
+
* Bind every guard this package calls to ApiKeyError, so an argument-shape
|
|
298
|
+
* failure anywhere carries one class and one code to branch on.
|
|
299
|
+
*
|
|
300
|
+
* @type {import('@exortek/shared/asserts').WrapFn}
|
|
301
|
+
*/
|
|
302
|
+
const wrap = (message, extra) => new ApiKeyError(ErrorCode.INVALID_ARGUMENT, message, extra);
|
|
303
|
+
|
|
304
|
+
const invalidArgument = makeInvalidArgument(wrap);
|
|
559
305
|
|
|
560
306
|
/**
|
|
561
307
|
* Scope match helpers.
|
|
@@ -1,4 +1,99 @@
|
|
|
1
|
+
type ApiKeyRecord = {
|
|
2
|
+
/**
|
|
3
|
+
* Plaintext lookup key (128-bit b64u).
|
|
4
|
+
*/
|
|
5
|
+
id: string;
|
|
6
|
+
/**
|
|
7
|
+
* Storage hash of the secret (43-char b64u).
|
|
8
|
+
*/
|
|
9
|
+
hash: string;
|
|
10
|
+
/**
|
|
11
|
+
* The prefix the key was minted with.
|
|
12
|
+
*/
|
|
13
|
+
prefix: string;
|
|
14
|
+
userId: string;
|
|
15
|
+
scopes: string[];
|
|
16
|
+
/**
|
|
17
|
+
* Human label ("Production Backend").
|
|
18
|
+
*/
|
|
19
|
+
name?: string | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* `'live'` / `'test'` / caller-defined.
|
|
22
|
+
*/
|
|
23
|
+
environment?: string | undefined;
|
|
24
|
+
metadata?: Record<string, unknown> | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* ms epoch.
|
|
27
|
+
*/
|
|
28
|
+
createdAt: number;
|
|
29
|
+
/**
|
|
30
|
+
* ms epoch; absent = no expiry.
|
|
31
|
+
*/
|
|
32
|
+
expiresAt?: number | undefined;
|
|
33
|
+
/**
|
|
34
|
+
* ms epoch when the record was revoked.
|
|
35
|
+
*/
|
|
36
|
+
revokedAt?: number | undefined;
|
|
37
|
+
revokedReason?: string | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* ms epoch of the last successful verify.
|
|
40
|
+
*/
|
|
41
|
+
lastUsedAt?: number | undefined;
|
|
42
|
+
/**
|
|
43
|
+
* Index into the peppers array that was used at mint. 0 = newest.
|
|
44
|
+
*/
|
|
45
|
+
pepperVersion?: number | undefined;
|
|
46
|
+
};
|
|
47
|
+
type ApiKeyStore = {
|
|
48
|
+
put: (record: ApiKeyRecord) => Promise<void>;
|
|
49
|
+
getById: (id: string) => Promise<ApiKeyRecord | null>;
|
|
50
|
+
update: (id: string, patch: Partial<ApiKeyRecord>) => Promise<ApiKeyRecord | null>;
|
|
51
|
+
revoke: (id: string, reason?: string) => Promise<boolean>;
|
|
52
|
+
revokeAllForUser: (userId: string, reason?: string) => Promise<number>;
|
|
53
|
+
listByUser: (userId: string) => Promise<ApiKeyRecord[]>;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
type AdapterContext = {
|
|
57
|
+
getHeader: (name: string) => string | undefined;
|
|
58
|
+
method?: string | undefined;
|
|
59
|
+
ip?: string | undefined;
|
|
60
|
+
query?: Record<string, unknown> | undefined;
|
|
61
|
+
};
|
|
62
|
+
type ApiKeyMiddlewareOptions = {
|
|
63
|
+
store: ApiKeyStore;
|
|
64
|
+
peppers?: any[] | undefined;
|
|
65
|
+
requiredScopes?: string[] | undefined;
|
|
66
|
+
expectedPrefix?: string | undefined;
|
|
67
|
+
updateLastUsed?: boolean | undefined;
|
|
68
|
+
/**
|
|
69
|
+
* Case-insensitive. The default reads `Authorization: Bearer <key>`;
|
|
70
|
+
* a `x-api-key` config reads `X-API-Key: <key>` directly.
|
|
71
|
+
*/
|
|
72
|
+
headerName?: string | undefined;
|
|
73
|
+
/**
|
|
74
|
+
* `'bearer'` expects `Bearer <key>`; `'raw'` uses the header value as-is.
|
|
75
|
+
*/
|
|
76
|
+
scheme?: "bearer" | "raw" | undefined;
|
|
77
|
+
/**
|
|
78
|
+
* When true, falls back to `?api_key=<key>` if no matching header is
|
|
79
|
+
* found. Discouraged because query strings leak into access logs and
|
|
80
|
+
* referer headers — off by default.
|
|
81
|
+
*/
|
|
82
|
+
allowQueryParam?: boolean | undefined;
|
|
83
|
+
queryParamName?: string | undefined;
|
|
84
|
+
/**
|
|
85
|
+
* Property name attached to the request object on success.
|
|
86
|
+
*/
|
|
87
|
+
attach?: string | undefined;
|
|
88
|
+
/**
|
|
89
|
+
* Override the default extraction entirely.
|
|
90
|
+
*/
|
|
91
|
+
tokenFromRequest?: ((ctx: AdapterContext) => string | undefined) | undefined;
|
|
92
|
+
};
|
|
93
|
+
|
|
1
94
|
/**
|
|
2
95
|
* @param {import('./core.js').ApiKeyMiddlewareOptions} options
|
|
3
96
|
*/
|
|
4
|
-
|
|
97
|
+
declare function apiKeyMiddleware(options: ApiKeyMiddlewareOptions): (req: any, res: any, next: any) => Promise<any>;
|
|
98
|
+
|
|
99
|
+
export { apiKeyMiddleware };
|