@stackwright-pro/auth 0.2.0-alpha.3 → 0.2.0-alpha.5
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/LICENSE +21 -0
- package/dist/index.d.mts +131 -3
- package/dist/index.d.ts +131 -3
- package/dist/index.js +416 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +410 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -210,6 +210,8 @@ var AuditEventType = /* @__PURE__ */ ((AuditEventType2) => {
|
|
|
210
210
|
AuditEventType2["PKI_CERT_VALIDATED"] = "pki.cert.validated";
|
|
211
211
|
AuditEventType2["PKI_CERT_REJECTED"] = "pki.cert.rejected";
|
|
212
212
|
AuditEventType2["PKI_HEADER_SIG_FAILED"] = "pki.header_sig.failed";
|
|
213
|
+
AuditEventType2["PKI_CERT_REVOKED"] = "pki.cert.revoked";
|
|
214
|
+
AuditEventType2["PKI_REVOCATION_CHECK_FAILED"] = "pki.revocation_check.failed";
|
|
213
215
|
AuditEventType2["OIDC_STATE_MISMATCH"] = "oidc.state_mismatch";
|
|
214
216
|
AuditEventType2["OIDC_TOKEN_EXCHANGE"] = "oidc.token_exchange";
|
|
215
217
|
AuditEventType2["OIDC_NONCE_MISMATCH"] = "oidc.nonce_mismatch";
|
|
@@ -242,13 +244,380 @@ function createAuditEvent(type, outcome, details) {
|
|
|
242
244
|
};
|
|
243
245
|
}
|
|
244
246
|
|
|
247
|
+
// src/pki/revocation-checker.ts
|
|
248
|
+
var RevocationCache = class {
|
|
249
|
+
store = /* @__PURE__ */ new Map();
|
|
250
|
+
maxAgeMs;
|
|
251
|
+
constructor(cacheMaxAgeSecs = 300) {
|
|
252
|
+
this.maxAgeMs = cacheMaxAgeSecs * 1e3;
|
|
253
|
+
}
|
|
254
|
+
get(serialNumber) {
|
|
255
|
+
const entry = this.store.get(serialNumber);
|
|
256
|
+
if (!entry) return null;
|
|
257
|
+
if (Date.now() > entry.expiresAt) {
|
|
258
|
+
this.store.delete(serialNumber);
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
return entry.status;
|
|
262
|
+
}
|
|
263
|
+
set(serialNumber, status) {
|
|
264
|
+
this.store.set(serialNumber, {
|
|
265
|
+
status,
|
|
266
|
+
expiresAt: Date.now() + this.maxAgeMs
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
/** Invalidate a single entry (e.g. after a forced re-check) */
|
|
270
|
+
invalidate(serialNumber) {
|
|
271
|
+
this.store.delete(serialNumber);
|
|
272
|
+
}
|
|
273
|
+
/** Number of cached entries (for testing/monitoring) */
|
|
274
|
+
get size() {
|
|
275
|
+
return this.store.size;
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
var SkipRevocationChecker = class {
|
|
279
|
+
reason;
|
|
280
|
+
constructor(reason = "Revocation checking delegated to upstream gateway") {
|
|
281
|
+
this.reason = reason;
|
|
282
|
+
}
|
|
283
|
+
async check(_input) {
|
|
284
|
+
return { revoked: false, skipped: true, reason: this.reason };
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
var CRLRevocationChecker = class {
|
|
288
|
+
cache;
|
|
289
|
+
config;
|
|
290
|
+
constructor(config) {
|
|
291
|
+
this.config = config;
|
|
292
|
+
this.cache = new RevocationCache(config.cacheMaxAge ?? 300);
|
|
293
|
+
}
|
|
294
|
+
async check(input) {
|
|
295
|
+
const { serialNumber } = input;
|
|
296
|
+
const crlUrl = this.config.crlDistributionPoint;
|
|
297
|
+
if (!crlUrl) {
|
|
298
|
+
if (this.config.hardFail) {
|
|
299
|
+
throw new Error("[revocation] CRL strategy requires crlDistributionPoint to be configured");
|
|
300
|
+
}
|
|
301
|
+
return {
|
|
302
|
+
revoked: false,
|
|
303
|
+
skipped: true,
|
|
304
|
+
reason: "CRL distribution point not configured"
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
const cached = this.cache.get(serialNumber);
|
|
308
|
+
if (cached !== null) return cached;
|
|
309
|
+
let derBuffer;
|
|
310
|
+
try {
|
|
311
|
+
const controller = new AbortController();
|
|
312
|
+
const timer = setTimeout(
|
|
313
|
+
() => controller.abort(),
|
|
314
|
+
this.config.timeoutMs ?? 5e3
|
|
315
|
+
);
|
|
316
|
+
const response = await fetch(crlUrl, {
|
|
317
|
+
signal: controller.signal,
|
|
318
|
+
headers: { Accept: "application/pkix-crl" }
|
|
319
|
+
});
|
|
320
|
+
clearTimeout(timer);
|
|
321
|
+
if (!response.ok) {
|
|
322
|
+
throw new Error(`CRL fetch returned HTTP ${response.status}`);
|
|
323
|
+
}
|
|
324
|
+
derBuffer = await response.arrayBuffer();
|
|
325
|
+
} catch (err) {
|
|
326
|
+
if (this.config.hardFail) {
|
|
327
|
+
throw new Error(`[revocation] CRL fetch failed (hardFail=true): ${String(err)}`);
|
|
328
|
+
}
|
|
329
|
+
return { revoked: false, skipped: true, reason: `CRL fetch failed: ${String(err)}` };
|
|
330
|
+
}
|
|
331
|
+
let revokedSerials;
|
|
332
|
+
try {
|
|
333
|
+
revokedSerials = parseCRLRevokedSerials(Buffer.from(derBuffer));
|
|
334
|
+
} catch (err) {
|
|
335
|
+
if (this.config.hardFail) {
|
|
336
|
+
throw new Error(`[revocation] CRL parse failed (hardFail=true): ${String(err)}`);
|
|
337
|
+
}
|
|
338
|
+
return { revoked: false, skipped: true, reason: `CRL parse failed: ${String(err)}` };
|
|
339
|
+
}
|
|
340
|
+
const normalizedSerial = normalizeSerial(serialNumber);
|
|
341
|
+
const isRevoked = revokedSerials.has(normalizedSerial);
|
|
342
|
+
const status = isRevoked ? { revoked: true, reason: "Certificate found in CRL" } : { revoked: false };
|
|
343
|
+
this.cache.set(serialNumber, status);
|
|
344
|
+
return status;
|
|
345
|
+
}
|
|
346
|
+
/** Exposed for testing */
|
|
347
|
+
get _cache() {
|
|
348
|
+
return this.cache;
|
|
349
|
+
}
|
|
350
|
+
};
|
|
351
|
+
var OCSPRevocationChecker = class {
|
|
352
|
+
cache;
|
|
353
|
+
config;
|
|
354
|
+
constructor(config) {
|
|
355
|
+
this.config = config;
|
|
356
|
+
this.cache = new RevocationCache(config.cacheMaxAge ?? 300);
|
|
357
|
+
}
|
|
358
|
+
async check(input) {
|
|
359
|
+
const { serialNumber } = input;
|
|
360
|
+
const ocspUrl = this.config.ocspResponderUrl;
|
|
361
|
+
if (!ocspUrl) {
|
|
362
|
+
if (this.config.hardFail) {
|
|
363
|
+
throw new Error("[revocation] OCSP strategy requires ocspResponderUrl to be configured");
|
|
364
|
+
}
|
|
365
|
+
return {
|
|
366
|
+
revoked: false,
|
|
367
|
+
skipped: true,
|
|
368
|
+
reason: "OCSP responder URL not configured"
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
const cached = this.cache.get(serialNumber);
|
|
372
|
+
if (cached !== null) return cached;
|
|
373
|
+
let response;
|
|
374
|
+
try {
|
|
375
|
+
const ocspRequest = buildOCSPGetRequest(ocspUrl, serialNumber);
|
|
376
|
+
const controller = new AbortController();
|
|
377
|
+
const timer = setTimeout(
|
|
378
|
+
() => controller.abort(),
|
|
379
|
+
this.config.timeoutMs ?? 5e3
|
|
380
|
+
);
|
|
381
|
+
response = await fetch(ocspRequest, {
|
|
382
|
+
signal: controller.signal,
|
|
383
|
+
headers: { Accept: "application/ocsp-response" }
|
|
384
|
+
});
|
|
385
|
+
clearTimeout(timer);
|
|
386
|
+
} catch (err) {
|
|
387
|
+
if (this.config.hardFail) {
|
|
388
|
+
throw new Error(`[revocation] OCSP request failed (hardFail=true): ${String(err)}`);
|
|
389
|
+
}
|
|
390
|
+
return { revoked: false, skipped: true, reason: `OCSP request failed: ${String(err)}` };
|
|
391
|
+
}
|
|
392
|
+
if (!response.ok) {
|
|
393
|
+
if (this.config.hardFail) {
|
|
394
|
+
throw new Error(
|
|
395
|
+
`[revocation] OCSP responder returned HTTP ${response.status} (hardFail=true)`
|
|
396
|
+
);
|
|
397
|
+
}
|
|
398
|
+
const skippedStatus = {
|
|
399
|
+
revoked: false,
|
|
400
|
+
skipped: true,
|
|
401
|
+
reason: `OCSP responder returned HTTP ${response.status}`
|
|
402
|
+
};
|
|
403
|
+
this.cache.set(serialNumber, skippedStatus);
|
|
404
|
+
return skippedStatus;
|
|
405
|
+
}
|
|
406
|
+
let status;
|
|
407
|
+
try {
|
|
408
|
+
const derBuffer = await response.arrayBuffer();
|
|
409
|
+
status = parseOCSPResponse(Buffer.from(derBuffer), serialNumber);
|
|
410
|
+
} catch (err) {
|
|
411
|
+
if (this.config.hardFail) {
|
|
412
|
+
throw new Error(`[revocation] OCSP response parse failed (hardFail=true): ${String(err)}`);
|
|
413
|
+
}
|
|
414
|
+
return { revoked: false, skipped: true, reason: `OCSP parse failed: ${String(err)}` };
|
|
415
|
+
}
|
|
416
|
+
this.cache.set(serialNumber, status);
|
|
417
|
+
return status;
|
|
418
|
+
}
|
|
419
|
+
/** Exposed for testing */
|
|
420
|
+
get _cache() {
|
|
421
|
+
return this.cache;
|
|
422
|
+
}
|
|
423
|
+
};
|
|
424
|
+
var CompositeRevocationChecker = class {
|
|
425
|
+
ocsp;
|
|
426
|
+
crl;
|
|
427
|
+
constructor(config) {
|
|
428
|
+
this.ocsp = new OCSPRevocationChecker({ ...config, hardFail: false });
|
|
429
|
+
this.crl = new CRLRevocationChecker(config);
|
|
430
|
+
}
|
|
431
|
+
async check(input) {
|
|
432
|
+
const ocspResult = await this.ocsp.check(input);
|
|
433
|
+
if (!("skipped" in ocspResult && ocspResult.skipped)) {
|
|
434
|
+
return ocspResult;
|
|
435
|
+
}
|
|
436
|
+
return this.crl.check(input);
|
|
437
|
+
}
|
|
438
|
+
};
|
|
439
|
+
function createRevocationChecker(config) {
|
|
440
|
+
switch (config.strategy) {
|
|
441
|
+
case "ocsp":
|
|
442
|
+
return new OCSPRevocationChecker(config);
|
|
443
|
+
case "crl":
|
|
444
|
+
return new CRLRevocationChecker(config);
|
|
445
|
+
case "ocsp_with_crl_fallback":
|
|
446
|
+
return new CompositeRevocationChecker(config);
|
|
447
|
+
case "skip":
|
|
448
|
+
default:
|
|
449
|
+
return new SkipRevocationChecker();
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
function normalizeSerial(serial) {
|
|
453
|
+
const clean = serial.replace(/[:\s]/g, "").replace(/^0x/i, "").toUpperCase();
|
|
454
|
+
return clean.replace(/^0+(?=.)/, "") || "0";
|
|
455
|
+
}
|
|
456
|
+
function parseCRLRevokedSerials(der) {
|
|
457
|
+
const serials = /* @__PURE__ */ new Set();
|
|
458
|
+
const tbsCertList = unwrapSequence(unwrapSequence(der));
|
|
459
|
+
let offset = 0;
|
|
460
|
+
let revokedSeqOffset = -1;
|
|
461
|
+
while (offset < tbsCertList.length - 2) {
|
|
462
|
+
const tag = tbsCertList[offset];
|
|
463
|
+
if (tag === void 0) break;
|
|
464
|
+
const { length: len, headerLen } = readTLVLength(tbsCertList, offset + 1);
|
|
465
|
+
if (tag === 48 && len > 0) {
|
|
466
|
+
const inner = tbsCertList.slice(offset + headerLen, offset + headerLen + len);
|
|
467
|
+
if (inner.length > 0 && inner[0] === 48) {
|
|
468
|
+
revokedSeqOffset = offset + headerLen;
|
|
469
|
+
break;
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
offset += headerLen + len;
|
|
473
|
+
}
|
|
474
|
+
if (revokedSeqOffset === -1) {
|
|
475
|
+
return serials;
|
|
476
|
+
}
|
|
477
|
+
const revokedBlock = tbsCertList.slice(revokedSeqOffset);
|
|
478
|
+
let pos = 0;
|
|
479
|
+
while (pos < revokedBlock.length - 2) {
|
|
480
|
+
const tag = revokedBlock[pos];
|
|
481
|
+
if (tag !== 48) break;
|
|
482
|
+
const { length: entryLen, headerLen: entryHdrLen } = readTLVLength(revokedBlock, pos + 1);
|
|
483
|
+
const entry = revokedBlock.slice(pos + entryHdrLen, pos + entryHdrLen + entryLen);
|
|
484
|
+
if (entry.length > 0 && entry[0] === 2) {
|
|
485
|
+
const { length: intLen, headerLen: intHdrLen } = readTLVLength(entry, 1);
|
|
486
|
+
const serialBytes = entry.slice(intHdrLen, intHdrLen + intLen);
|
|
487
|
+
const trimmed = serialBytes[0] === 0 && serialBytes.length > 1 ? serialBytes.slice(1) : serialBytes;
|
|
488
|
+
const hexSerial = trimmed.toString("hex").toUpperCase().replace(/^0+(?=.)/, "");
|
|
489
|
+
serials.add(hexSerial || "0");
|
|
490
|
+
}
|
|
491
|
+
pos += entryHdrLen + entryLen;
|
|
492
|
+
}
|
|
493
|
+
return serials;
|
|
494
|
+
}
|
|
495
|
+
function unwrapSequence(der) {
|
|
496
|
+
if (der[0] !== 48) {
|
|
497
|
+
throw new Error(`Expected SEQUENCE (0x30), got 0x${der[0]?.toString(16)}`);
|
|
498
|
+
}
|
|
499
|
+
const { length, headerLen } = readTLVLength(der, 1);
|
|
500
|
+
return der.slice(headerLen, headerLen + length);
|
|
501
|
+
}
|
|
502
|
+
function readTLVLength(buf, offset) {
|
|
503
|
+
const firstByte = buf[offset];
|
|
504
|
+
if (firstByte === void 0) throw new Error("Unexpected end of DER data");
|
|
505
|
+
if ((firstByte & 128) === 0) {
|
|
506
|
+
return { length: firstByte, headerLen: 2 };
|
|
507
|
+
}
|
|
508
|
+
const numLenBytes = firstByte & 127;
|
|
509
|
+
let length = 0;
|
|
510
|
+
for (let i = 1; i <= numLenBytes; i++) {
|
|
511
|
+
const b = buf[offset + i];
|
|
512
|
+
if (b === void 0) throw new Error("Unexpected end of DER length encoding");
|
|
513
|
+
length = length << 8 | b;
|
|
514
|
+
}
|
|
515
|
+
return { length, headerLen: 2 + numLenBytes };
|
|
516
|
+
}
|
|
517
|
+
function buildOCSPGetRequest(baseUrl, serialNumber) {
|
|
518
|
+
const serialHex = normalizeSerial(serialNumber);
|
|
519
|
+
const serialBuf = Buffer.from(serialHex.length % 2 === 0 ? serialHex : "0" + serialHex, "hex");
|
|
520
|
+
const serialDer = (serialBuf[0] & 128) !== 0 ? Buffer.concat([Buffer.from([0]), serialBuf]) : serialBuf;
|
|
521
|
+
const sha1Oid = Buffer.from([
|
|
522
|
+
48,
|
|
523
|
+
9,
|
|
524
|
+
// SEQUENCE, 9 bytes
|
|
525
|
+
6,
|
|
526
|
+
5,
|
|
527
|
+
43,
|
|
528
|
+
14,
|
|
529
|
+
3,
|
|
530
|
+
2,
|
|
531
|
+
26,
|
|
532
|
+
// OID 1.3.14.3.2.26 (SHA-1)
|
|
533
|
+
5,
|
|
534
|
+
0
|
|
535
|
+
// NULL
|
|
536
|
+
]);
|
|
537
|
+
const zeroHash = Buffer.alloc(20, 0);
|
|
538
|
+
const issuerNameHashDer = derOctetString(zeroHash);
|
|
539
|
+
const issuerKeyHashDer = derOctetString(zeroHash);
|
|
540
|
+
const serialDerTagged = derInteger(serialDer);
|
|
541
|
+
const certId = derSequence(
|
|
542
|
+
Buffer.concat([sha1Oid, issuerNameHashDer, issuerKeyHashDer, serialDerTagged])
|
|
543
|
+
);
|
|
544
|
+
const requestItem = derSequence(certId);
|
|
545
|
+
const requestList = derSequence(requestItem);
|
|
546
|
+
const tbsRequest = derSequence(requestList);
|
|
547
|
+
const ocspRequest = derSequence(tbsRequest);
|
|
548
|
+
const b64 = ocspRequest.toString("base64url");
|
|
549
|
+
const separator = baseUrl.endsWith("/") ? "" : "/";
|
|
550
|
+
return `${baseUrl}${separator}${b64}`;
|
|
551
|
+
}
|
|
552
|
+
function parseOCSPResponse(der, _serialNumber) {
|
|
553
|
+
const ocspResponse = unwrapSequence(der);
|
|
554
|
+
if (ocspResponse[0] !== 10) {
|
|
555
|
+
throw new Error("Expected ENUMERATED responseStatus in OCSPResponse");
|
|
556
|
+
}
|
|
557
|
+
const statusLen = ocspResponse[1] ?? 0;
|
|
558
|
+
const responseStatus = ocspResponse[2 + statusLen - 1] ?? 0;
|
|
559
|
+
if (responseStatus !== 0) {
|
|
560
|
+
const statusNames = {
|
|
561
|
+
1: "malformedRequest",
|
|
562
|
+
2: "internalError",
|
|
563
|
+
3: "tryLater",
|
|
564
|
+
5: "sigRequired",
|
|
565
|
+
6: "unauthorized"
|
|
566
|
+
};
|
|
567
|
+
throw new Error(
|
|
568
|
+
`OCSP responder returned non-success status: ${statusNames[responseStatus] ?? responseStatus}`
|
|
569
|
+
);
|
|
570
|
+
}
|
|
571
|
+
const derStr = ocspResponse.toString("hex");
|
|
572
|
+
if (derStr.includes("8000")) {
|
|
573
|
+
return { revoked: false };
|
|
574
|
+
}
|
|
575
|
+
if (derStr.includes("a1")) {
|
|
576
|
+
const revokedIdx = ocspResponse.indexOf(161);
|
|
577
|
+
if (revokedIdx !== -1) {
|
|
578
|
+
return {
|
|
579
|
+
revoked: true,
|
|
580
|
+
reason: "Certificate revoked per OCSP responder"
|
|
581
|
+
};
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
return { revoked: false };
|
|
585
|
+
}
|
|
586
|
+
function derTLV(tag, value) {
|
|
587
|
+
const lenBytes = encodeDERLength(value.length);
|
|
588
|
+
return Buffer.concat([Buffer.from([tag]), lenBytes, value]);
|
|
589
|
+
}
|
|
590
|
+
function derSequence(content) {
|
|
591
|
+
return derTLV(48, content);
|
|
592
|
+
}
|
|
593
|
+
function derOctetString(value) {
|
|
594
|
+
return derTLV(4, value);
|
|
595
|
+
}
|
|
596
|
+
function derInteger(value) {
|
|
597
|
+
return derTLV(2, value);
|
|
598
|
+
}
|
|
599
|
+
function encodeDERLength(len) {
|
|
600
|
+
if (len < 128) {
|
|
601
|
+
return Buffer.from([len]);
|
|
602
|
+
} else if (len < 256) {
|
|
603
|
+
return Buffer.from([129, len]);
|
|
604
|
+
} else if (len < 65536) {
|
|
605
|
+
return Buffer.from([130, len >> 8 & 255, len & 255]);
|
|
606
|
+
}
|
|
607
|
+
throw new Error(`DER length ${len} too large for this implementation`);
|
|
608
|
+
}
|
|
609
|
+
|
|
245
610
|
// src/providers/pki-provider.ts
|
|
246
611
|
var PKIProvider = class {
|
|
247
612
|
constructor(config, auditLogger) {
|
|
248
613
|
this.config = config;
|
|
249
614
|
this.auditLogger = auditLogger;
|
|
615
|
+
this.revocationChecker = createRevocationChecker(
|
|
616
|
+
config.revocationCheck ?? { strategy: "skip" }
|
|
617
|
+
);
|
|
250
618
|
}
|
|
251
619
|
auditLogger;
|
|
620
|
+
revocationChecker;
|
|
252
621
|
async authenticate(context) {
|
|
253
622
|
let parsed = null;
|
|
254
623
|
if (this.config.source === "gateway_headers") {
|
|
@@ -296,6 +665,39 @@ var PKIProvider = class {
|
|
|
296
665
|
}
|
|
297
666
|
return null;
|
|
298
667
|
}
|
|
668
|
+
const revocationInput = {
|
|
669
|
+
serialNumber: parsed.serialNumber,
|
|
670
|
+
issuerName: parsed.issuer.commonName
|
|
671
|
+
// certPem not available for gateway_headers source
|
|
672
|
+
};
|
|
673
|
+
try {
|
|
674
|
+
const revocationStatus = await this.revocationChecker.check(revocationInput);
|
|
675
|
+
if (revocationStatus.revoked) {
|
|
676
|
+
try {
|
|
677
|
+
this.auditLogger?.log(
|
|
678
|
+
createAuditEvent("pki.cert.revoked" /* PKI_CERT_REVOKED */, "failure", {
|
|
679
|
+
authMethod: "pki",
|
|
680
|
+
reason: "reason" in revocationStatus ? revocationStatus.reason : "Certificate revoked",
|
|
681
|
+
details: { serialNumber: parsed.serialNumber }
|
|
682
|
+
})
|
|
683
|
+
);
|
|
684
|
+
} catch {
|
|
685
|
+
}
|
|
686
|
+
return null;
|
|
687
|
+
}
|
|
688
|
+
} catch (err) {
|
|
689
|
+
try {
|
|
690
|
+
this.auditLogger?.log(
|
|
691
|
+
createAuditEvent("pki.revocation_check.failed" /* PKI_REVOCATION_CHECK_FAILED */, "failure", {
|
|
692
|
+
authMethod: "pki",
|
|
693
|
+
reason: String(err),
|
|
694
|
+
details: { serialNumber: parsed.serialNumber }
|
|
695
|
+
})
|
|
696
|
+
);
|
|
697
|
+
} catch {
|
|
698
|
+
}
|
|
699
|
+
return null;
|
|
700
|
+
}
|
|
299
701
|
if (this.config.profile === "dod_cac") {
|
|
300
702
|
if (!validateDoDCAC(parsed)) {
|
|
301
703
|
try {
|
|
@@ -411,7 +813,7 @@ async function discoverOIDC(discoveryUrl) {
|
|
|
411
813
|
return metadata;
|
|
412
814
|
} catch (error) {
|
|
413
815
|
if (error instanceof Error && error.name === "AbortError") {
|
|
414
|
-
throw new Error(`OIDC request timed out after 10s: ${discoveryUrl}
|
|
816
|
+
throw new Error(`OIDC request timed out after 10s: ${discoveryUrl}`, { cause: error });
|
|
415
817
|
}
|
|
416
818
|
throw error;
|
|
417
819
|
} finally {
|
|
@@ -473,7 +875,9 @@ async function exchangeCodeForTokens(metadata, code, clientId, clientSecret, red
|
|
|
473
875
|
return await response.json();
|
|
474
876
|
} catch (error) {
|
|
475
877
|
if (error instanceof Error && error.name === "AbortError") {
|
|
476
|
-
throw new Error(`OIDC request timed out after 10s: ${metadata.token_endpoint}
|
|
878
|
+
throw new Error(`OIDC request timed out after 10s: ${metadata.token_endpoint}`, {
|
|
879
|
+
cause: error
|
|
880
|
+
});
|
|
477
881
|
}
|
|
478
882
|
throw error;
|
|
479
883
|
} finally {
|
|
@@ -505,7 +909,9 @@ async function refreshAccessToken(metadata, refreshToken, clientId, clientSecret
|
|
|
505
909
|
return await response.json();
|
|
506
910
|
} catch (error) {
|
|
507
911
|
if (error instanceof Error && error.name === "AbortError") {
|
|
508
|
-
throw new Error(`OIDC request timed out after 10s: ${metadata.token_endpoint}
|
|
912
|
+
throw new Error(`OIDC request timed out after 10s: ${metadata.token_endpoint}`, {
|
|
913
|
+
cause: error
|
|
914
|
+
});
|
|
509
915
|
}
|
|
510
916
|
throw error;
|
|
511
917
|
} finally {
|
|
@@ -1594,21 +2000,27 @@ Object.defineProperty(exports, "rbacConfigSchema", {
|
|
|
1594
2000
|
exports.AuditEventType = AuditEventType;
|
|
1595
2001
|
exports.AuthContext = AuthContext;
|
|
1596
2002
|
exports.AuthProvider = AuthProvider;
|
|
2003
|
+
exports.CRLRevocationChecker = CRLRevocationChecker;
|
|
1597
2004
|
exports.CompositeAuditLogger = CompositeAuditLogger;
|
|
2005
|
+
exports.CompositeRevocationChecker = CompositeRevocationChecker;
|
|
1598
2006
|
exports.ConsoleAuditLogger = ConsoleAuditLogger;
|
|
1599
2007
|
exports.DOD_CAC_PROFILE = DOD_CAC_PROFILE;
|
|
1600
2008
|
exports.InMemoryRevocationStore = InMemoryRevocationStore;
|
|
1601
2009
|
exports.KeycloakAdapter = KeycloakAdapter;
|
|
1602
2010
|
exports.NoopAuditLogger = NoopAuditLogger;
|
|
2011
|
+
exports.OCSPRevocationChecker = OCSPRevocationChecker;
|
|
1603
2012
|
exports.OIDCProvider = OIDCProvider;
|
|
1604
2013
|
exports.PKIProvider = PKIProvider;
|
|
1605
2014
|
exports.RBACEngine = RBACEngine;
|
|
2015
|
+
exports.RevocationCache = RevocationCache;
|
|
1606
2016
|
exports.SessionManager = SessionManager;
|
|
2017
|
+
exports.SkipRevocationChecker = SkipRevocationChecker;
|
|
1607
2018
|
exports.buildAuthorizationUrl = buildAuthorizationUrl;
|
|
1608
2019
|
exports.clearCookie = clearCookie;
|
|
1609
2020
|
exports.createAuditEvent = createAuditEvent;
|
|
1610
2021
|
exports.createDoDCACConfig = createDoDCACConfig;
|
|
1611
2022
|
exports.createDoDCACDevConfig = createDoDCACDevConfig;
|
|
2023
|
+
exports.createRevocationChecker = createRevocationChecker;
|
|
1612
2024
|
exports.decryptToken = decryptToken;
|
|
1613
2025
|
exports.deriveEncryptionKey = deriveEncryptionKey;
|
|
1614
2026
|
exports.discoverOIDC = discoverOIDC;
|
|
@@ -1623,6 +2035,7 @@ exports.generateState = generateState;
|
|
|
1623
2035
|
exports.getAuthDecorator = getAuthDecorator;
|
|
1624
2036
|
exports.hasAuthConfig = hasAuthConfig;
|
|
1625
2037
|
exports.maybeWrapWithAuth = maybeWrapWithAuth;
|
|
2038
|
+
exports.normalizeSerial = normalizeSerial;
|
|
1626
2039
|
exports.parseCertFromHeaders = parseCertFromHeaders;
|
|
1627
2040
|
exports.parseCertificate = parseCertificate;
|
|
1628
2041
|
exports.parseCookies = parseCookies;
|