@blamejs/blamejs-shop 0.5.12 → 0.5.13
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 +2 -0
- package/lib/asset-manifest.json +1 -1
- package/lib/vendor/MANIFEST.json +632 -416
- package/lib/vendor/blamejs/.clusterfuzzlite/Dockerfile +21 -10
- package/lib/vendor/blamejs/.clusterfuzzlite/build.sh +30 -9
- package/lib/vendor/blamejs/.github/dependabot.yml +8 -0
- package/lib/vendor/blamejs/.github/workflows/actions-lint.yml +3 -3
- package/lib/vendor/blamejs/.github/workflows/cflite_batch.yml +7 -2
- package/lib/vendor/blamejs/.github/workflows/cflite_pr.yml +7 -2
- package/lib/vendor/blamejs/.github/workflows/ci.yml +21 -21
- package/lib/vendor/blamejs/.github/workflows/codeql.yml +3 -3
- package/lib/vendor/blamejs/.github/workflows/npm-publish.yml +4 -4
- package/lib/vendor/blamejs/.github/workflows/release-container.yml +7 -7
- package/lib/vendor/blamejs/.github/workflows/scorecard.yml +3 -3
- package/lib/vendor/blamejs/.github/workflows/sha-to-tag-verify.yml +1 -1
- package/lib/vendor/blamejs/.gitignore +2 -0
- package/lib/vendor/blamejs/CHANGELOG.md +122 -0
- package/lib/vendor/blamejs/NOTICE +26 -1
- package/lib/vendor/blamejs/SECURITY.md +1 -1
- package/lib/vendor/blamejs/api-snapshot.json +207 -5
- package/lib/vendor/blamejs/docker/keycloak/realm-blamejs-test.json +29 -0
- package/lib/vendor/blamejs/examples/wiki/DEPLOY.md +1 -0
- package/lib/vendor/blamejs/examples/wiki/lib/build-app.js +31 -0
- package/lib/vendor/blamejs/examples/wiki/lib/source-comment-block-validator.js +109 -0
- package/lib/vendor/blamejs/examples/wiki/nginx.conf +106 -0
- package/lib/vendor/blamejs/examples/wiki/package-lock.json +1 -1
- package/lib/vendor/blamejs/examples/wiki/test/e2e.js +92 -0
- package/lib/vendor/blamejs/fuzz/asn1-der.fuzz.js +28 -0
- package/lib/vendor/blamejs/fuzz/cms-codec.fuzz.js +17 -0
- package/lib/vendor/blamejs/fuzz/link-header.fuzz.js +18 -0
- package/lib/vendor/blamejs/index.js +6 -0
- package/lib/vendor/blamejs/lib/a2a.js +4 -4
- package/lib/vendor/blamejs/lib/agent-idempotency.js +18 -2
- package/lib/vendor/blamejs/lib/agent-saga.js +36 -8
- package/lib/vendor/blamejs/lib/agent-snapshot.js +63 -6
- package/lib/vendor/blamejs/lib/app-shutdown.js +23 -20
- package/lib/vendor/blamejs/lib/archive-read.js +8 -0
- package/lib/vendor/blamejs/lib/archive-tar.js +12 -2
- package/lib/vendor/blamejs/lib/arg-parser.js +49 -5
- package/lib/vendor/blamejs/lib/asn1-der.js +12 -0
- package/lib/vendor/blamejs/lib/audit-sign.js +47 -1
- package/lib/vendor/blamejs/lib/audit.js +71 -8
- package/lib/vendor/blamejs/lib/auth/ciba.js +14 -2
- package/lib/vendor/blamejs/lib/auth/fido-mds3.js +58 -47
- package/lib/vendor/blamejs/lib/auth/jwt.js +34 -0
- package/lib/vendor/blamejs/lib/auth/oauth.js +90 -13
- package/lib/vendor/blamejs/lib/auth/oid4vci.js +20 -17
- package/lib/vendor/blamejs/lib/auth/openid-federation.js +214 -23
- package/lib/vendor/blamejs/lib/auth/saml.js +38 -20
- package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +10 -4
- package/lib/vendor/blamejs/lib/backup/bundle.js +13 -3
- package/lib/vendor/blamejs/lib/backup/index.js +16 -5
- package/lib/vendor/blamejs/lib/backup/manifest.js +18 -5
- package/lib/vendor/blamejs/lib/base32.js +21 -0
- package/lib/vendor/blamejs/lib/break-glass.js +19 -10
- package/lib/vendor/blamejs/lib/bundler.js +5 -1
- package/lib/vendor/blamejs/lib/cache-status.js +3 -7
- package/lib/vendor/blamejs/lib/calendar.js +21 -1
- package/lib/vendor/blamejs/lib/cbor.js +12 -1
- package/lib/vendor/blamejs/lib/cert.js +29 -11
- package/lib/vendor/blamejs/lib/cli.js +94 -24
- package/lib/vendor/blamejs/lib/cloud-events.js +2 -2
- package/lib/vendor/blamejs/lib/cluster-provider-db.js +13 -3
- package/lib/vendor/blamejs/lib/codepoint-class.js +85 -0
- package/lib/vendor/blamejs/lib/compliance-ai-act-prohibited.js +8 -4
- package/lib/vendor/blamejs/lib/compliance-ai-act-transparency.js +19 -4
- package/lib/vendor/blamejs/lib/compliance-ai-act.js +6 -8
- package/lib/vendor/blamejs/lib/content-credentials.js +1 -1
- package/lib/vendor/blamejs/lib/content-digest.js +2 -1
- package/lib/vendor/blamejs/lib/cookies.js +13 -3
- package/lib/vendor/blamejs/lib/cose.js +31 -16
- package/lib/vendor/blamejs/lib/crypto-field.js +32 -0
- package/lib/vendor/blamejs/lib/crypto-oprf.js +11 -2
- package/lib/vendor/blamejs/lib/crypto-xwing.js +22 -4
- package/lib/vendor/blamejs/lib/crypto.js +314 -19
- package/lib/vendor/blamejs/lib/csp.js +11 -3
- package/lib/vendor/blamejs/lib/daemon.js +270 -24
- package/lib/vendor/blamejs/lib/dark-patterns.js +5 -2
- package/lib/vendor/blamejs/lib/db-declare-view.js +2 -2
- package/lib/vendor/blamejs/lib/db-query.js +34 -7
- package/lib/vendor/blamejs/lib/db.js +18 -6
- package/lib/vendor/blamejs/lib/dbsc.js +17 -0
- package/lib/vendor/blamejs/lib/dev.js +21 -2
- package/lib/vendor/blamejs/lib/dsr.js +157 -102
- package/lib/vendor/blamejs/lib/external-db.js +41 -2
- package/lib/vendor/blamejs/lib/file-upload.js +25 -7
- package/lib/vendor/blamejs/lib/flag-providers.js +27 -15
- package/lib/vendor/blamejs/lib/forms.js +113 -27
- package/lib/vendor/blamejs/lib/gate-contract.js +23 -10
- package/lib/vendor/blamejs/lib/gdpr-ropa.js +8 -1
- package/lib/vendor/blamejs/lib/guard-agent-registry.js +1 -1
- package/lib/vendor/blamejs/lib/guard-archive.js +2 -2
- package/lib/vendor/blamejs/lib/guard-cidr.js +27 -1
- package/lib/vendor/blamejs/lib/guard-graphql.js +30 -11
- package/lib/vendor/blamejs/lib/guard-html.js +26 -53
- package/lib/vendor/blamejs/lib/guard-image.js +24 -5
- package/lib/vendor/blamejs/lib/guard-imap-command.js +10 -2
- package/lib/vendor/blamejs/lib/guard-jmap.js +19 -3
- package/lib/vendor/blamejs/lib/guard-jwt.js +18 -2
- package/lib/vendor/blamejs/lib/guard-list-unsubscribe.js +2 -2
- package/lib/vendor/blamejs/lib/guard-managesieve-command.js +10 -2
- package/lib/vendor/blamejs/lib/guard-markdown.js +11 -24
- package/lib/vendor/blamejs/lib/guard-pdf.js +18 -2
- package/lib/vendor/blamejs/lib/guard-pop3-command.js +10 -2
- package/lib/vendor/blamejs/lib/guard-regex.js +8 -5
- package/lib/vendor/blamejs/lib/guard-svg.js +31 -32
- package/lib/vendor/blamejs/lib/guard-time.js +1 -1
- package/lib/vendor/blamejs/lib/guard-uuid.js +2 -2
- package/lib/vendor/blamejs/lib/html-balance.js +3 -3
- package/lib/vendor/blamejs/lib/http-client-cache.js +82 -4
- package/lib/vendor/blamejs/lib/http-client-cookie-jar.js +16 -1
- package/lib/vendor/blamejs/lib/http-client.js +39 -7
- package/lib/vendor/blamejs/lib/http-message-signature.js +35 -1
- package/lib/vendor/blamejs/lib/i18n-messageformat.js +31 -6
- package/lib/vendor/blamejs/lib/i18n.js +35 -21
- package/lib/vendor/blamejs/lib/incident-report.js +8 -1
- package/lib/vendor/blamejs/lib/ip-utils.js +11 -1
- package/lib/vendor/blamejs/lib/json-path.js +23 -1
- package/lib/vendor/blamejs/lib/jwk.js +20 -3
- package/lib/vendor/blamejs/lib/link-header.js +2 -1
- package/lib/vendor/blamejs/lib/log-stream-otlp-grpc.js +5 -1
- package/lib/vendor/blamejs/lib/log-stream-otlp.js +5 -1
- package/lib/vendor/blamejs/lib/log-stream.js +8 -3
- package/lib/vendor/blamejs/lib/mail-auth.js +123 -22
- package/lib/vendor/blamejs/lib/mail-bimi.js +1 -1
- package/lib/vendor/blamejs/lib/mail-bounce.js +8 -0
- package/lib/vendor/blamejs/lib/mail-crypto-pgp.js +46 -10
- package/lib/vendor/blamejs/lib/mail-dav.js +22 -3
- package/lib/vendor/blamejs/lib/mail-dkim.js +96 -30
- package/lib/vendor/blamejs/lib/mail-helo.js +6 -1
- package/lib/vendor/blamejs/lib/mail-scan.js +23 -16
- package/lib/vendor/blamejs/lib/mail-send-deliver.js +34 -8
- package/lib/vendor/blamejs/lib/mail-server-imap.js +3 -4
- package/lib/vendor/blamejs/lib/mail-server-managesieve.js +7 -11
- package/lib/vendor/blamejs/lib/mail-server-mx.js +93 -7
- package/lib/vendor/blamejs/lib/mail-server-registry.js +8 -2
- package/lib/vendor/blamejs/lib/mail.js +15 -5
- package/lib/vendor/blamejs/lib/metrics.js +268 -63
- package/lib/vendor/blamejs/lib/middleware/age-gate.js +7 -1
- package/lib/vendor/blamejs/lib/middleware/asyncapi-serve.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/body-parser.js +19 -4
- package/lib/vendor/blamejs/lib/middleware/bot-guard.js +5 -9
- package/lib/vendor/blamejs/lib/middleware/csp-report.js +40 -8
- package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +24 -10
- package/lib/vendor/blamejs/lib/middleware/dpop.js +10 -5
- package/lib/vendor/blamejs/lib/middleware/index.js +6 -1
- package/lib/vendor/blamejs/lib/middleware/nel.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/openapi-serve.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/rate-limit.js +12 -1
- package/lib/vendor/blamejs/lib/middleware/require-bound-key.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/scim-server.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/tus-upload.js +6 -2
- package/lib/vendor/blamejs/lib/mtls-ca.js +18 -2
- package/lib/vendor/blamejs/lib/network-dns-resolver.js +11 -1
- package/lib/vendor/blamejs/lib/network-dns.js +21 -2
- package/lib/vendor/blamejs/lib/network-tls.js +69 -7
- package/lib/vendor/blamejs/lib/nonce-store.js +9 -1
- package/lib/vendor/blamejs/lib/object-store/gcs.js +7 -0
- package/lib/vendor/blamejs/lib/object-store/sigv4.js +31 -0
- package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +1 -1
- package/lib/vendor/blamejs/lib/outbox.js +1 -1
- package/lib/vendor/blamejs/lib/parsers/safe-ini.js +9 -1
- package/lib/vendor/blamejs/lib/parsers/safe-toml.js +10 -1
- package/lib/vendor/blamejs/lib/permissions.js +6 -3
- package/lib/vendor/blamejs/lib/pid-probe.js +55 -0
- package/lib/vendor/blamejs/lib/pqc-agent.js +8 -1
- package/lib/vendor/blamejs/lib/pqc-software.js +3 -3
- package/lib/vendor/blamejs/lib/pubsub.js +20 -9
- package/lib/vendor/blamejs/lib/queue-local.js +8 -1
- package/lib/vendor/blamejs/lib/queue-redis.js +5 -0
- package/lib/vendor/blamejs/lib/redact.js +54 -0
- package/lib/vendor/blamejs/lib/restore-bundle.js +10 -2
- package/lib/vendor/blamejs/lib/restore.js +19 -0
- package/lib/vendor/blamejs/lib/retention.js +12 -4
- package/lib/vendor/blamejs/lib/router.js +60 -6
- package/lib/vendor/blamejs/lib/safe-buffer.js +69 -0
- package/lib/vendor/blamejs/lib/safe-decompress.js +8 -2
- package/lib/vendor/blamejs/lib/safe-dns.js +25 -20
- package/lib/vendor/blamejs/lib/safe-ical.js +7 -3
- package/lib/vendor/blamejs/lib/safe-mime.js +12 -1
- package/lib/vendor/blamejs/lib/safe-object.js +80 -0
- package/lib/vendor/blamejs/lib/safe-path.js +52 -4
- package/lib/vendor/blamejs/lib/safe-redirect.js +10 -2
- package/lib/vendor/blamejs/lib/safe-schema.js +4 -1
- package/lib/vendor/blamejs/lib/safe-sieve.js +33 -1
- package/lib/vendor/blamejs/lib/safe-sql.js +88 -0
- package/lib/vendor/blamejs/lib/safe-vcard.js +7 -3
- package/lib/vendor/blamejs/lib/scheduler.js +8 -1
- package/lib/vendor/blamejs/lib/security-assert.js +6 -6
- package/lib/vendor/blamejs/lib/self-update-standalone-verifier.js +74 -27
- package/lib/vendor/blamejs/lib/self-update.js +517 -87
- package/lib/vendor/blamejs/lib/server-timing.js +2 -4
- package/lib/vendor/blamejs/lib/session.js +34 -12
- package/lib/vendor/blamejs/lib/sql.js +15 -1
- package/lib/vendor/blamejs/lib/ssrf-guard.js +52 -0
- package/lib/vendor/blamejs/lib/static.js +55 -13
- package/lib/vendor/blamejs/lib/storage.js +8 -2
- package/lib/vendor/blamejs/lib/subject.js +6 -1
- package/lib/vendor/blamejs/lib/tenant-quota.js +52 -13
- package/lib/vendor/blamejs/lib/tls-exporter.js +3 -3
- package/lib/vendor/blamejs/lib/tsa.js +34 -13
- package/lib/vendor/blamejs/lib/uri-template.js +8 -1
- package/lib/vendor/blamejs/lib/vault/index.js +13 -0
- package/lib/vendor/blamejs/lib/vc.js +44 -5
- package/lib/vendor/blamejs/lib/vendor/MANIFEST.json +26 -26
- package/lib/vendor/blamejs/lib/vendor/noble-ciphers.cjs +792 -1
- package/lib/vendor/blamejs/lib/vendor/noble-curves.cjs +3443 -1
- package/lib/vendor/blamejs/lib/vendor/noble-post-quantum.cjs +2737 -1
- package/lib/vendor/blamejs/lib/vendor/pki.cjs +39550 -13
- package/lib/vendor/blamejs/lib/vendor/public-suffix-list.dat +55 -53
- package/lib/vendor/blamejs/lib/vendor/public-suffix-list.data.js +5551 -5554
- package/lib/vendor/blamejs/lib/vendor/simplewebauthn-server.cjs +22459 -32
- package/lib/vendor/blamejs/lib/watcher.js +89 -17
- package/lib/vendor/blamejs/lib/webhook-dispatcher.js +25 -3
- package/lib/vendor/blamejs/lib/webhook.js +12 -2
- package/lib/vendor/blamejs/lib/ws-client.js +32 -1
- package/lib/vendor/blamejs/lib/xml-c14n.js +29 -1
- package/lib/vendor/blamejs/oss-fuzz/projects/blamejs/Dockerfile +1 -1
- package/lib/vendor/blamejs/package-lock.json +2 -2
- package/lib/vendor/blamejs/package.json +1 -1
- package/lib/vendor/blamejs/release-notes/v0.16.x.json +1462 -0
- package/lib/vendor/blamejs/release-notes/v0.17.0.json +31 -0
- package/lib/vendor/blamejs/release-notes/v0.17.1.json +31 -0
- package/lib/vendor/blamejs/release-notes/v0.17.10.json +30 -0
- package/lib/vendor/blamejs/release-notes/v0.17.11.json +22 -0
- package/lib/vendor/blamejs/release-notes/v0.17.12.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.17.13.json +77 -0
- package/lib/vendor/blamejs/release-notes/v0.17.14.json +40 -0
- package/lib/vendor/blamejs/release-notes/v0.17.15.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.17.16.json +27 -0
- package/lib/vendor/blamejs/release-notes/v0.17.17.json +31 -0
- package/lib/vendor/blamejs/release-notes/v0.17.18.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.17.19.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.17.2.json +26 -0
- package/lib/vendor/blamejs/release-notes/v0.17.20.json +43 -0
- package/lib/vendor/blamejs/release-notes/v0.17.21.json +26 -0
- package/lib/vendor/blamejs/release-notes/v0.17.22.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.17.3.json +43 -0
- package/lib/vendor/blamejs/release-notes/v0.17.4.json +35 -0
- package/lib/vendor/blamejs/release-notes/v0.17.5.json +26 -0
- package/lib/vendor/blamejs/release-notes/v0.17.6.json +26 -0
- package/lib/vendor/blamejs/release-notes/v0.17.7.json +35 -0
- package/lib/vendor/blamejs/release-notes/v0.17.8.json +22 -0
- package/lib/vendor/blamejs/release-notes/v0.17.9.json +26 -0
- package/lib/vendor/blamejs/scripts/validate-source-comment-blocks.js +4 -0
- package/lib/vendor/blamejs/scripts/vendor-update.sh +293 -9
- package/lib/vendor/blamejs/socket.yml +94 -0
- package/lib/vendor/blamejs/test/00-primitives.js +605 -0
- package/lib/vendor/blamejs/test/helpers/drivers.js +12 -9
- package/lib/vendor/blamejs/test/integration/audit-stack-mysql.test.js +90 -1
- package/lib/vendor/blamejs/test/integration/audit-stack-postgres.test.js +122 -1
- package/lib/vendor/blamejs/test/integration/data-layer-mysql.test.js +30 -0
- package/lib/vendor/blamejs/test/integration/data-layer-pg.test.js +29 -0
- package/lib/vendor/blamejs/test/integration/dsr-cluster-mysql.test.js +479 -0
- package/lib/vendor/blamejs/test/integration/dsr-cluster-pg.test.js +487 -0
- package/lib/vendor/blamejs/test/integration/federation-auth.test.js +313 -5
- package/lib/vendor/blamejs/test/integration/mail-dkim.test.js +80 -0
- package/lib/vendor/blamejs/test/integration/openid-federation-chain.test.js +275 -0
- package/lib/vendor/blamejs/test/integration/webhook-dispatcher-pg.test.js +96 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/a2a-tasks.test.js +401 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/acme.test.js +1649 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/age-gate.test.js +33 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-idempotency.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-saga.test.js +60 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-snapshot.test.js +524 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/api-encrypt.test.js +891 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/app-shutdown.test.js +128 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/archive-adapters.test.js +271 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/archive-read.test.js +628 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/archive-tar-read.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/archive-wrap.test.js +227 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/arg-parser.test.js +15 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/asn1-der.test.js +73 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file.test.js +114 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-sign-anchor.test.js +141 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-tools.test.js +624 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit.test.js +769 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-jwt-defenses.test.js +436 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-oauth.test.js +1697 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-oid4vp.test.js +495 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-password.test.js +500 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-saml.test.js +1809 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-status-list.test.js +243 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/backup-index.test.js +2226 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/backup-manifest-signature.test.js +183 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/base32.test.js +105 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/break-glass.test.js +693 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cache.test.js +603 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/calendar.test.js +557 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/case-insensitive-security-token-guard.test.js +214 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cbor.test.js +25 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cert.test.js +843 -6
- package/lib/vendor/blamejs/test/layer-0-primitives/ciba-authreqid-binding.test.js +77 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/ciba.test.js +866 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/clear-site-data.test.js +18 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-erase.test.js +19 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli.test.js +2790 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cluster-lease-renewal-ttl.test.js +114 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cluster.test.js +1032 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cms-codec.test.js +575 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +739 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/codepoint-class.test.js +8 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance-ai-act.test.js +194 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance-lifecycle-proto-key.test.js +104 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance-sanctions.test.js +254 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/content-credentials.test.js +613 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/cookies.test.js +140 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cose.test.js +407 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-adversarial.test.js +352 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-derived-hash.test.js +32 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field.test.js +575 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-files-parallel.test.js +10 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-stream.test.js +24 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-oprf.test.js +17 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-spki-pin.test.js +183 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-xwing.test.js +48 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto.test.js +345 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/csp-report.test.js +58 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/csv.test.js +48 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/daemon.test.js +459 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/dark-patterns.test.js +19 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-query.test.js +1019 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-raw-residency-gate.test.js +77 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db.test.js +1621 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ddl-change-control.test.js +462 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/dnssec.test.js +323 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dpop-middleware-verify.test.js +562 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dsr.test.js +901 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/dual-control.test.js +249 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/external-db-migrate.test.js +561 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/external-db.test.js +1214 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/fal.test.js +21 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/fedcm-dbsc.test.js +46 -20
- package/lib/vendor/blamejs/test/layer-0-primitives/federation-vc-suite.test.js +147 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/fido-mds3.test.js +907 -38
- package/lib/vendor/blamejs/test/layer-0-primitives/file-upload-content-safety-skip-audit.test.js +29 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/file-upload.test.js +1135 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/flag.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/forms.test.js +747 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/gate-contract.test.js +1855 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/gdpr-ropa.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-archive.test.js +86 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-auth.test.js +117 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-cidr.test.js +151 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-domain.test.js +422 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-filename.test.js +424 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/{guard-gate-disposition-coverage.test.js → guard-gate-disposition.test.js} +1 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-graphql.test.js +340 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-html.test.js +29 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-idempotency-key.test.js +28 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-image.test.js +519 -45
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-imap-command.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-jmap.test.js +51 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-jsonpath.test.js +66 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-jwt.test.js +436 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-managesieve-command.test.js +25 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-markdown.test.js +16 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-mime.test.js +86 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-oauth.test.js +140 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-pdf.test.js +80 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-pop3-command.test.js +27 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-regex.test.js +99 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-shell.test.js +76 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/{guard-sql-coverage.test.js → guard-sql.test.js} +3 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-svg.test.js +524 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-template.test.js +71 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-time.test.js +92 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-uuid.test.js +86 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/html-balance.test.js +38 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-client-cache-authorization.test.js +347 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-client-cache.test.js +908 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-client.test.js +2874 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-message-signature.test.js +643 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/i18n-messageformat.test.js +38 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/i18n.test.js +1153 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/idempotency-key.test.js +494 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ip-utils.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/jsdoc-example-execution.test.js +177 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/json-path.test.js +103 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/json-schema.test.js +214 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/jwk.test.js +41 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/jwt-external.test.js +276 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/keychain.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/log-stream.test.js +241 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/log.test.js +106 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-agent.test.js +441 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth.test.js +2136 -4
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-bimi.test.js +759 -12
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-bounce.test.js +811 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp-experimental.test.js +401 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp.test.js +751 -8
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-smime.test.js +864 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto.test.js +110 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-dav.test.js +830 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-deploy.test.js +635 -86
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-dkim.test.js +818 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-helo.test.js +27 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-scan.test.js +199 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-send-deliver.test.js +686 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-imap.test.js +778 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-jmap.test.js +1438 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-managesieve.test.js +449 -6
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-mx.test.js +773 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-pop3.test.js +623 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-rate-limit.test.js +55 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-registry.test.js +13 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-submission.test.js +877 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-sieve.test.js +326 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-store-fts.test.js +55 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-store.test.js +242 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail.test.js +1596 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/mcp.test.js +440 -4
- package/lib/vendor/blamejs/test/layer-0-primitives/metrics-snapshot.test.js +89 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/metrics.test.js +1230 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-assetlinks.test.js +113 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-body-parser.test.js +1169 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-bot-disclose.test.js +123 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-cookies.test.js +108 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-gpc.test.js +121 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-headers.test.js +163 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-host-allowlist.test.js +154 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-require-content-type.test.js +127 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/{middleware-tus-upload-coverage.test.js → middleware-tus-upload.test.js} +45 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-web-app-manifest.test.js +132 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mtls-ca-crl-fingerprint-only.test.js +92 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-dns-resolver.test.js +65 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-dns.test.js +1727 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/network-nts.test.js +699 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-smtp-policy.test.js +1181 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-tls.test.js +1876 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/network.test.js +32 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/nonce-store-enforce-replay-nonboolean.test.js +81 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ntp-check.test.js +122 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/observability-tracing.test.js +378 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/observability.test.js +77 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/oid4vci.test.js +1016 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/openid-federation.test.js +946 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/outbox.test.js +818 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/own-property-membership-guards.test.js +109 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/parsers-safe-toml.test.js +543 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/{parsers-safe-yaml-coverage.test.js → parsers-safe-yaml.test.js} +2 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/parsers-standalone.test.js +73 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/passkey.test.js +649 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/permissions.test.js +524 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/pqc-agent-curve.test.js +22 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/pubsub.test.js +295 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/queue-flow-repeat.test.js +36 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/queue.test.js +83 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/rate-limit-xff-spoofing.test.js +34 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/redact.test.js +1031 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/request-helpers.test.js +94 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/require-bound-key.test.js +401 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/restore-empty-manifest-wipe.test.js +154 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/retention.test.js +600 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/router-host-path-injection.test.js +231 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/router-tls0rtt.test.js +21 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/router.test.js +1277 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-async.test.js +133 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer-linear-scans.test.js +14 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer.test.js +80 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-decompress.test.js +28 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-dns.test.js +245 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-ical.test.js +32 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-ini.test.js +376 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-json.test.js +175 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-mime.test.js +518 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-object.test.js +62 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-path.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-schema.test.js +104 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-sql.test.js +142 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-url.test.js +112 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-vcard.test.js +26 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/scheduler.test.js +157 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/scim-server.test.js +396 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sd-jwt-vc.test.js +930 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/security-assert.test.js +755 -82
- package/lib/vendor/blamejs/test/layer-0-primitives/self-update.test.js +1053 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/session-device-binding.test.js +200 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/session-strict-binding-missing-failclosed.test.js +110 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sigv4-bucket-ops.test.js +636 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sql-offset-without-limit.test.js +94 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sql.test.js +1190 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ssrf-guard.test.js +21 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/static.test.js +850 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/storage-presigned-url.test.js +146 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/storage.test.js +621 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/subject.test.js +47 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/template.test.js +582 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/tenant-quota.test.js +587 -25
- package/lib/vendor/blamejs/test/layer-0-primitives/time.test.js +11 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/tsa.test.js +524 -63
- package/lib/vendor/blamejs/test/layer-0-primitives/uri-template.test.js +27 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/vault-rotate.test.js +866 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/vault.test.js +74 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/vc.test.js +215 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/watcher.test.js +550 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/webhook-dispatcher.test.js +388 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/webhook.test.js +262 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/websocket.test.js +1294 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ws-client.test.js +629 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/xml-c14n-attr-normalization.test.js +164 -0
- package/lib/vendor/blamejs/test/smoke.js +2 -0
- package/package.json +1 -1
- package/lib/vendor/blamejs/release-notes/v0.16.0.json +0 -44
- package/lib/vendor/blamejs/release-notes/v0.16.1.json +0 -36
- package/lib/vendor/blamejs/release-notes/v0.16.2.json +0 -71
- package/lib/vendor/blamejs/release-notes/v0.16.3.json +0 -71
- package/lib/vendor/blamejs/test/layer-0-primitives/acme-coverage.test.js +0 -441
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-oauth-coverage.test.js +0 -482
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-saml-coverage.test.js +0 -671
- package/lib/vendor/blamejs/test/layer-0-primitives/backup-index-coverage.test.js +0 -690
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-coverage.test.js +0 -238
- package/lib/vendor/blamejs/test/layer-0-primitives/content-credentials-coverage.test.js +0 -319
- package/lib/vendor/blamejs/test/layer-0-primitives/keychain-coverage.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth-coverage.test.js +0 -437
- package/lib/vendor/blamejs/test/layer-0-primitives/mcp-coverage.test.js +0 -443
- package/lib/vendor/blamejs/test/layer-0-primitives/metrics-coverage.test.js +0 -395
- package/lib/vendor/blamejs/test/layer-0-primitives/network-smtp-policy-coverage.test.js +0 -565
- package/lib/vendor/blamejs/test/layer-0-primitives/router-coverage.test.js +0 -592
- package/lib/vendor/blamejs/test/layer-0-primitives/sql-coverage.test.js +0 -422
- package/lib/vendor/blamejs/test/layer-0-primitives/test-coverage.test.js +0 -573
|
@@ -0,0 +1,562 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (c) blamejs contributors
|
|
3
|
+
"use strict";
|
|
4
|
+
/**
|
|
5
|
+
* b.middleware.dpop — request-path verification, the server-managed nonce
|
|
6
|
+
* challenge lifecycle (RFC 9449 §8), access-token (ath) binding, the getNonce
|
|
7
|
+
* callback, htu reconstruction edges, DPoP-header shape enforcement (§4.1), and
|
|
8
|
+
* the 401 response-shaping knobs (onDeny / problemDetails / audit).
|
|
9
|
+
*
|
|
10
|
+
* These drive the exported middleware — b.middleware.dpop(opts) — with real
|
|
11
|
+
* DPoP proofs built by b.auth.dpop.buildProof (node:crypto keypairs), exercising
|
|
12
|
+
* the adversarial branches a proof-of-possession verifier must fail closed on:
|
|
13
|
+
*
|
|
14
|
+
* - a stale / missing / wrong / malformed server-managed nonce
|
|
15
|
+
* - a proof whose ath does not bind the presented access token
|
|
16
|
+
* - an htu that cannot be reconstructed, or carries a stale iat, or a
|
|
17
|
+
* disallowed algorithm, or a mismatched method
|
|
18
|
+
* - two proofs smuggled in one comma-joined header value, and an
|
|
19
|
+
* array-valued DPoP header (§4.1: exactly one proof per request)
|
|
20
|
+
*
|
|
21
|
+
* A verify that accepted any of these would be a fail-open proof gate.
|
|
22
|
+
*
|
|
23
|
+
* Run standalone: node test/layer-0-primitives/dpop-middleware-verify.test.js
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
var nodeCrypto = require("node:crypto");
|
|
27
|
+
var helpers = require("../helpers");
|
|
28
|
+
var b = helpers.b;
|
|
29
|
+
var check = helpers.check;
|
|
30
|
+
|
|
31
|
+
var HTU = "https://api.example.com/resource";
|
|
32
|
+
var HTM = "POST";
|
|
33
|
+
|
|
34
|
+
function _ns() { return b.nonceStore.create({ backend: "memory" }); }
|
|
35
|
+
|
|
36
|
+
function _ecPem() {
|
|
37
|
+
var kp = nodeCrypto.generateKeyPairSync("ec", { namedCurve: "prime256v1" });
|
|
38
|
+
return kp.privateKey.export({ type: "pkcs8", format: "pem" });
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function _proof(keyPem, over) {
|
|
42
|
+
var o = {
|
|
43
|
+
htm: HTM,
|
|
44
|
+
htu: HTU,
|
|
45
|
+
privateKey: keyPem,
|
|
46
|
+
algorithm: "ES256",
|
|
47
|
+
};
|
|
48
|
+
if (over) for (var k in over) o[k] = over[k];
|
|
49
|
+
return b.auth.dpop.buildProof(o);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Hand-sign a proof from an explicit header/payload so tests can smuggle a
|
|
53
|
+
// nonce claim of a hostile shape (empty string / number) that buildProof would
|
|
54
|
+
// never emit — the malformed value must still be rejected by the middleware's
|
|
55
|
+
// server-managed nonce check after the signature verifies.
|
|
56
|
+
function _b64url(buf) {
|
|
57
|
+
return Buffer.from(buf).toString("base64")
|
|
58
|
+
.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
59
|
+
}
|
|
60
|
+
function _handSign(keyPem, payload) {
|
|
61
|
+
var priv = nodeCrypto.createPrivateKey({ key: keyPem, format: "pem" });
|
|
62
|
+
var pubJwk = nodeCrypto.createPublicKey(priv).export({ format: "jwk" });
|
|
63
|
+
var header = { typ: "dpop+jwt", alg: "ES256", jwk: { kty: "EC", crv: pubJwk.crv, x: pubJwk.x, y: pubJwk.y } };
|
|
64
|
+
var signingInput = _b64url(JSON.stringify(header)) + "." + _b64url(JSON.stringify(payload));
|
|
65
|
+
var sig = nodeCrypto.sign("sha256", Buffer.from(signingInput, "ascii"), { key: priv, dsaEncoding: "ieee-p1363" });
|
|
66
|
+
return signingInput + "." + _b64url(sig);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// mockReq/mockRes are the framework's own fixtures (b.testing.*); reuse them
|
|
70
|
+
// rather than hand-rolling a res shape.
|
|
71
|
+
function _req(over) {
|
|
72
|
+
var opts = {
|
|
73
|
+
method: HTM,
|
|
74
|
+
url: "/resource",
|
|
75
|
+
headers: { host: "api.example.com" },
|
|
76
|
+
socket: { remoteAddress: "203.0.113.9", encrypted: true },
|
|
77
|
+
};
|
|
78
|
+
if (over) for (var k in over) {
|
|
79
|
+
if (k === "headers") { for (var h in over.headers) opts.headers[h] = over.headers[h]; }
|
|
80
|
+
else opts[k] = over[k];
|
|
81
|
+
}
|
|
82
|
+
return b.testing.mockReq(opts);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Drive one request through the middleware; capture status / body / headers /
|
|
86
|
+
// whether next() ran.
|
|
87
|
+
async function _call(mw, req) {
|
|
88
|
+
var res = b.testing.mockRes();
|
|
89
|
+
var nextCalled = false;
|
|
90
|
+
await mw(req, res, function () { nextCalled = true; });
|
|
91
|
+
var cap = res._captured();
|
|
92
|
+
return { res: res, cap: cap, nextCalled: nextCalled, status: cap.status, req: req };
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// ---- server-managed nonce (requireNonce) challenge + accept round trip ----
|
|
96
|
+
|
|
97
|
+
async function testNonceChallengeAndAccept() {
|
|
98
|
+
var key = _ecPem();
|
|
99
|
+
var mw = b.middleware.dpop({
|
|
100
|
+
replayStore: _ns(),
|
|
101
|
+
requireNonce: true,
|
|
102
|
+
getHtu: function () { return HTU; },
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// 1) No proof at all → 401 use_dpop_nonce + a fresh DPoP-Nonce challenge.
|
|
106
|
+
var r1 = await _call(mw, _req());
|
|
107
|
+
check("nonce challenge: no-proof request is 401", r1.status === 401);
|
|
108
|
+
check("nonce challenge: error is use_dpop_nonce", /use_dpop_nonce/.test(r1.cap.body));
|
|
109
|
+
var n1 = r1.cap.headers["dpop-nonce"];
|
|
110
|
+
check("nonce challenge: server issues a DPoP-Nonce header", typeof n1 === "string" && n1.length > 0);
|
|
111
|
+
|
|
112
|
+
// 2) A proof carrying the issued nonce is accepted → next() runs, req.dpop set,
|
|
113
|
+
// and the response refreshes DPoP-Nonce.
|
|
114
|
+
var goodProof = await _proof(key, { nonce: n1 });
|
|
115
|
+
var r2 = await _call(mw, _req({ headers: { dpop: goodProof } }));
|
|
116
|
+
check("nonce accept: valid nonce → next() called", r2.nextCalled === true);
|
|
117
|
+
check("nonce accept: req.dpop attached with jkt", r2.req.dpop && typeof r2.req.dpop.jkt === "string");
|
|
118
|
+
check("nonce accept: response refreshes DPoP-Nonce", typeof r2.res.getHeader("DPoP-Nonce") === "string");
|
|
119
|
+
|
|
120
|
+
// 3) A proof WITHOUT a nonce (but otherwise valid) → verify passes, the
|
|
121
|
+
// server-managed check rejects → 401 use_dpop_nonce. Fail closed.
|
|
122
|
+
var noNonce = await _proof(key);
|
|
123
|
+
var r3 = await _call(mw, _req({ headers: { dpop: noNonce } }));
|
|
124
|
+
check("nonce missing: proof lacking a nonce is refused (401)", r3.status === 401);
|
|
125
|
+
check("nonce missing: refusal is use_dpop_nonce", /use_dpop_nonce/.test(r3.cap.body));
|
|
126
|
+
check("nonce missing: handler not reached", r3.req.dpop === undefined && r3.nextCalled === false);
|
|
127
|
+
|
|
128
|
+
// 4) A proof carrying a WRONG (unrecognized) nonce → 401. Not fail-open.
|
|
129
|
+
var wrongProof = await _proof(key, { nonce: "AAAAAAAAAAAAAAAAAAAAAA" });
|
|
130
|
+
var r4 = await _call(mw, _req({ headers: { dpop: wrongProof } }));
|
|
131
|
+
check("nonce wrong: unrecognized nonce is refused (401)", r4.status === 401);
|
|
132
|
+
check("nonce wrong: handler not reached", r4.nextCalled === false);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// A malformed nonce claim (empty string / non-string) inside an otherwise-valid
|
|
136
|
+
// signed proof must not slip past the rolling-pair accept check.
|
|
137
|
+
async function testMalformedNonceClaimRefused() {
|
|
138
|
+
var key = _ecPem();
|
|
139
|
+
var mw = b.middleware.dpop({
|
|
140
|
+
replayStore: _ns(),
|
|
141
|
+
requireNonce: true,
|
|
142
|
+
getHtu: function () { return HTU; },
|
|
143
|
+
});
|
|
144
|
+
var iat = Math.floor(Date.now() / 1000);
|
|
145
|
+
|
|
146
|
+
// The empty-string / non-string nonce claims sit in a validly-signed proof,
|
|
147
|
+
// so verify() passes and the server-managed nonce check is what must reject
|
|
148
|
+
// them — asserting use_dpop_nonce proves we reached that check rather than
|
|
149
|
+
// bouncing off a signature failure.
|
|
150
|
+
var emptyNonce = _handSign(key, { jti: "jti-empty-1", htm: HTM, htu: HTU, iat: iat, nonce: "" });
|
|
151
|
+
var rEmpty = await _call(mw, _req({ headers: { dpop: emptyNonce } }));
|
|
152
|
+
check("nonce empty-string claim: refused via the nonce check (use_dpop_nonce)",
|
|
153
|
+
rEmpty.status === 401 && rEmpty.nextCalled === false && /use_dpop_nonce/.test(rEmpty.cap.body));
|
|
154
|
+
|
|
155
|
+
var numNonce = _handSign(key, { jti: "jti-num-1", htm: HTM, htu: HTU, iat: iat, nonce: 12345 });
|
|
156
|
+
var rNum = await _call(mw, _req({ headers: { dpop: numNonce } }));
|
|
157
|
+
check("nonce non-string claim: refused via the nonce check (use_dpop_nonce)",
|
|
158
|
+
rNum.status === 401 && rNum.nextCalled === false && /use_dpop_nonce/.test(rNum.cap.body));
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// The rolling pair keeps the previous nonce valid across a rotation so an
|
|
162
|
+
// in-flight client one rotation behind is not kicked off (RFC 9449 §8).
|
|
163
|
+
async function testNoncePreviousAcceptedAcrossRotation() {
|
|
164
|
+
var key = _ecPem();
|
|
165
|
+
var t0 = Date.now();
|
|
166
|
+
var mw = b.middleware.dpop({
|
|
167
|
+
replayStore: _ns(),
|
|
168
|
+
requireNonce: true,
|
|
169
|
+
nonceRotateSec: 0.01, // 10ms — rotate lazily on the next access after the window
|
|
170
|
+
getHtu: function () { return HTU; },
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
// Issue the first (current) nonce via a challenge.
|
|
174
|
+
var r1 = await _call(mw, _req());
|
|
175
|
+
var n1 = r1.cap.headers["dpop-nonce"];
|
|
176
|
+
check("rotation: first nonce issued", typeof n1 === "string" && n1.length > 0);
|
|
177
|
+
|
|
178
|
+
// Let the rotation window elapse (poll, don't sleep). One waitUntil poll is
|
|
179
|
+
// ~25ms, comfortably past the 10ms window.
|
|
180
|
+
await helpers.waitUntil(function () { return Date.now() - t0 >= 40; }, {
|
|
181
|
+
timeoutMs: 5000,
|
|
182
|
+
label: "dpop nonce rotation: rotate window (10ms) elapsed",
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
// A proof built with the now-previous nonce n1 must still be accepted: the
|
|
186
|
+
// access rotates current→previous, and n1 matches previous.
|
|
187
|
+
var proofN1 = await _proof(key, { nonce: n1 });
|
|
188
|
+
var r2 = await _call(mw, _req({ headers: { dpop: proofN1 } }));
|
|
189
|
+
check("rotation: proof with the previous nonce still accepted", r2.nextCalled === true);
|
|
190
|
+
var n2 = r2.res.getHeader("DPoP-Nonce");
|
|
191
|
+
check("rotation: response carries the rotated (new current) nonce", typeof n2 === "string" && n2 !== n1);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// shutdown() drains the manager: it issues no fresh nonces and refuses every
|
|
195
|
+
// presented one, so the surrounding middleware 401s while the new instance owns
|
|
196
|
+
// the trust anchor.
|
|
197
|
+
async function testNonceManagerShutdown() {
|
|
198
|
+
var key = _ecPem();
|
|
199
|
+
var mw = b.middleware.dpop({
|
|
200
|
+
replayStore: _ns(),
|
|
201
|
+
requireNonce: true,
|
|
202
|
+
getHtu: function () { return HTU; },
|
|
203
|
+
});
|
|
204
|
+
var r1 = await _call(mw, _req());
|
|
205
|
+
var n1 = r1.cap.headers["dpop-nonce"];
|
|
206
|
+
|
|
207
|
+
mw.shutdown();
|
|
208
|
+
|
|
209
|
+
var proofN1 = await _proof(key, { nonce: n1 });
|
|
210
|
+
var r2 = await _call(mw, _req({ headers: { dpop: proofN1 } }));
|
|
211
|
+
check("shutdown: a previously-valid nonce is now refused (401)", r2.status === 401 && r2.nextCalled === false);
|
|
212
|
+
check("shutdown: no fresh DPoP-Nonce is issued", !r2.cap.headers["dpop-nonce"]);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// revoke() rotates both slots immediately: the outstanding nonce is invalidated
|
|
216
|
+
// but the manager keeps serving fresh nonces afterward.
|
|
217
|
+
async function testNonceManagerRevoke() {
|
|
218
|
+
var key = _ecPem();
|
|
219
|
+
var mw = b.middleware.dpop({
|
|
220
|
+
replayStore: _ns(),
|
|
221
|
+
requireNonce: true,
|
|
222
|
+
getHtu: function () { return HTU; },
|
|
223
|
+
});
|
|
224
|
+
var r1 = await _call(mw, _req());
|
|
225
|
+
var n1 = r1.cap.headers["dpop-nonce"];
|
|
226
|
+
|
|
227
|
+
mw.revoke();
|
|
228
|
+
|
|
229
|
+
// The old nonce is dead.
|
|
230
|
+
var proofOld = await _proof(key, { nonce: n1 });
|
|
231
|
+
var rOld = await _call(mw, _req({ headers: { dpop: proofOld } }));
|
|
232
|
+
check("revoke: the outstanding nonce is invalidated (401)", rOld.status === 401 && rOld.nextCalled === false);
|
|
233
|
+
|
|
234
|
+
// A fresh challenge yields a working new nonce.
|
|
235
|
+
var r2 = await _call(mw, _req());
|
|
236
|
+
var n2 = r2.cap.headers["dpop-nonce"];
|
|
237
|
+
check("revoke: manager still issues fresh nonces", typeof n2 === "string" && n2 !== n1);
|
|
238
|
+
var proofNew = await _proof(key, { nonce: n2 });
|
|
239
|
+
var rNew = await _call(mw, _req({ headers: { dpop: proofNew } }));
|
|
240
|
+
check("revoke: a proof with the new nonce is accepted", rNew.nextCalled === true);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// The lifecycle hooks are no-ops (never throw) when requireNonce is off.
|
|
244
|
+
function testLifecycleHooksNoopWithoutNonce() {
|
|
245
|
+
var mw = b.middleware.dpop({ replayStore: _ns() });
|
|
246
|
+
var threw = null;
|
|
247
|
+
try { mw.shutdown(); mw.revoke(); } catch (e) { threw = e; }
|
|
248
|
+
check("lifecycle: shutdown()/revoke() are no-ops when requireNonce is off", threw === null);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// ---- access-token (ath) binding ----
|
|
252
|
+
|
|
253
|
+
async function testAthBinding() {
|
|
254
|
+
var key = _ecPem();
|
|
255
|
+
var token = "access-token-abc123";
|
|
256
|
+
var mw = b.middleware.dpop({
|
|
257
|
+
replayStore: _ns(),
|
|
258
|
+
getHtu: function () { return HTU; },
|
|
259
|
+
getAccessToken: function () { return token; },
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
// Proof bound to the presented token → ath matches → next().
|
|
263
|
+
var bound = await _proof(key, { accessToken: token });
|
|
264
|
+
var rOk = await _call(mw, _req({ headers: { dpop: bound } }));
|
|
265
|
+
check("ath: proof bound to the presented token verifies", rOk.nextCalled === true);
|
|
266
|
+
|
|
267
|
+
// Proof with NO ath while a token is presented → 401 (missing-ath).
|
|
268
|
+
var noAth = await _proof(key);
|
|
269
|
+
var rMissing = await _call(mw, _req({ headers: { dpop: noAth } }));
|
|
270
|
+
check("ath: proof with no ath but a presented token is refused", rMissing.status === 401 && rMissing.nextCalled === false);
|
|
271
|
+
|
|
272
|
+
// Proof bound to a DIFFERENT token → 401 (ath-mismatch). Not fail-open.
|
|
273
|
+
var otherBound = await _proof(key, { accessToken: "some-other-token" });
|
|
274
|
+
var rMismatch = await _call(mw, _req({ headers: { dpop: otherBound } }));
|
|
275
|
+
check("ath: proof bound to a different token is refused", rMismatch.status === 401 && rMismatch.nextCalled === false);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// A throwing getAccessToken is swallowed (drop-silent request-shape reader): the
|
|
279
|
+
// proof proceeds without ath binding rather than crashing the request.
|
|
280
|
+
async function testGetAccessTokenThrowSwallowed() {
|
|
281
|
+
var key = _ecPem();
|
|
282
|
+
var mw = b.middleware.dpop({
|
|
283
|
+
replayStore: _ns(),
|
|
284
|
+
getHtu: function () { return HTU; },
|
|
285
|
+
getAccessToken: function () { throw new Error("boom extracting bearer"); },
|
|
286
|
+
});
|
|
287
|
+
var proof = await _proof(key);
|
|
288
|
+
var r = await _call(mw, _req({ headers: { dpop: proof } }));
|
|
289
|
+
check("getAccessToken throw: swallowed → no ath enforced → proof proceeds", r.nextCalled === true);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// ---- getNonce callback (operator-owned nonce, requireNonce off) ----
|
|
293
|
+
|
|
294
|
+
async function testGetNonceCallback() {
|
|
295
|
+
var key = _ecPem();
|
|
296
|
+
var serverNonce = "server-issued-nonce-xyz";
|
|
297
|
+
var mw = b.middleware.dpop({
|
|
298
|
+
replayStore: _ns(),
|
|
299
|
+
getHtu: function () { return HTU; },
|
|
300
|
+
getNonce: function () { return serverNonce; },
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
// Proof carrying the expected nonce → next().
|
|
304
|
+
var good = await _proof(key, { nonce: serverNonce });
|
|
305
|
+
var rOk = await _call(mw, _req({ headers: { dpop: good } }));
|
|
306
|
+
check("getNonce: proof with the expected nonce verifies", rOk.nextCalled === true);
|
|
307
|
+
|
|
308
|
+
// Proof with no nonce → verify throws missing-nonce → 401 use_dpop_nonce.
|
|
309
|
+
var noNonce = await _proof(key);
|
|
310
|
+
var rMissing = await _call(mw, _req({ headers: { dpop: noNonce } }));
|
|
311
|
+
check("getNonce: missing nonce is refused with use_dpop_nonce",
|
|
312
|
+
rMissing.status === 401 && /use_dpop_nonce/.test(rMissing.cap.body) && rMissing.nextCalled === false);
|
|
313
|
+
|
|
314
|
+
// Proof with a mismatched nonce → 401 use_dpop_nonce.
|
|
315
|
+
var wrong = await _proof(key, { nonce: "not-the-server-nonce" });
|
|
316
|
+
var rWrong = await _call(mw, _req({ headers: { dpop: wrong } }));
|
|
317
|
+
check("getNonce: mismatched nonce is refused with use_dpop_nonce",
|
|
318
|
+
rWrong.status === 401 && /use_dpop_nonce/.test(rWrong.cap.body));
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// getNonce returning null skips nonce enforcement; a throwing getNonce is
|
|
322
|
+
// swallowed the same way (documented drop-silent).
|
|
323
|
+
async function testGetNonceNullAndThrow() {
|
|
324
|
+
var key = _ecPem();
|
|
325
|
+
var mwNull = b.middleware.dpop({
|
|
326
|
+
replayStore: _ns(),
|
|
327
|
+
getHtu: function () { return HTU; },
|
|
328
|
+
getNonce: function () { return null; },
|
|
329
|
+
});
|
|
330
|
+
var p1 = await _proof(key);
|
|
331
|
+
var r1 = await _call(mwNull, _req({ headers: { dpop: p1 } }));
|
|
332
|
+
check("getNonce null: nonce enforcement skipped → proof proceeds", r1.nextCalled === true);
|
|
333
|
+
|
|
334
|
+
var mwThrow = b.middleware.dpop({
|
|
335
|
+
replayStore: _ns(),
|
|
336
|
+
getHtu: function () { return HTU; },
|
|
337
|
+
getNonce: function () { throw new Error("nonce lookup failed"); },
|
|
338
|
+
});
|
|
339
|
+
var p2 = await _proof(key);
|
|
340
|
+
var r2 = await _call(mwThrow, _req({ headers: { dpop: p2 } }));
|
|
341
|
+
check("getNonce throw: swallowed → proof proceeds", r2.nextCalled === true);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// ---- htu reconstruction edges + method binding ----
|
|
345
|
+
|
|
346
|
+
async function testHtuReconstructStripsQueryAndFragment() {
|
|
347
|
+
var key = _ecPem();
|
|
348
|
+
|
|
349
|
+
// No getHtu: proto/host are reconstructed from the (TLS) socket + Host header.
|
|
350
|
+
// The proof binds https://api.example.com/resource; the request URL carries a
|
|
351
|
+
// query + fragment that must be stripped before comparison (RFC 9449 §4.3).
|
|
352
|
+
var proof = await _proof(key);
|
|
353
|
+
var rQ = await _call(b.middleware.dpop({ replayStore: _ns() }),
|
|
354
|
+
_req({ url: "/resource?foo=1&bar=2", headers: { dpop: proof } }));
|
|
355
|
+
check("htu: query string is stripped before comparison → proof verifies", rQ.nextCalled === true);
|
|
356
|
+
|
|
357
|
+
var proof2 = await _proof(key, { jti: "jti-frag-1" });
|
|
358
|
+
var rF = await _call(b.middleware.dpop({ replayStore: _ns() }),
|
|
359
|
+
_req({ url: "/resource#section", headers: { dpop: proof2 } }));
|
|
360
|
+
check("htu: fragment is stripped before comparison → proof verifies", rF.nextCalled === true);
|
|
361
|
+
|
|
362
|
+
// A request with no url reconstructs the root path "/".
|
|
363
|
+
var rootProof = await _proof(key, { htu: "https://api.example.com/", jti: "jti-root-1" });
|
|
364
|
+
var rootReq = b.testing.mockReq({ method: HTM, headers: { host: "api.example.com", dpop: rootProof }, socket: { encrypted: true } });
|
|
365
|
+
delete rootReq.url;
|
|
366
|
+
var rRoot = await _call(b.middleware.dpop({ replayStore: _ns() }), rootReq);
|
|
367
|
+
check("htu: absent url reconstructs the root path → proof verifies", rRoot.nextCalled === true);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
async function testHtuCannotReconstruct() {
|
|
371
|
+
var key = _ecPem();
|
|
372
|
+
|
|
373
|
+
// getHtu returns an empty string → htu falsy → 401 "could not reconstruct".
|
|
374
|
+
var mwEmpty = b.middleware.dpop({ replayStore: _ns(), getHtu: function () { return ""; } });
|
|
375
|
+
var proof = await _proof(key);
|
|
376
|
+
var rEmpty = await _call(mwEmpty, _req({ headers: { dpop: proof } }));
|
|
377
|
+
check("htu empty: getHtu returning '' → 401 could not reconstruct",
|
|
378
|
+
rEmpty.status === 401 && /could not reconstruct/.test(rEmpty.cap.body));
|
|
379
|
+
|
|
380
|
+
// No Host header + no forwarded trust → default host resolver returns null →
|
|
381
|
+
// reconstruction fails → 401.
|
|
382
|
+
var mwRecon = b.middleware.dpop({ replayStore: _ns() });
|
|
383
|
+
var proof2 = await _proof(key, { jti: "jti-nohost-1" });
|
|
384
|
+
var noHostReq = b.testing.mockReq({ method: HTM, url: "/resource", headers: { dpop: proof2 }, socket: { remoteAddress: "203.0.113.9", encrypted: true } });
|
|
385
|
+
delete noHostReq.headers.host;
|
|
386
|
+
var rRecon = await _call(mwRecon, noHostReq);
|
|
387
|
+
check("htu no-host: reconstruction fails → 401", rRecon.status === 401 && rRecon.nextCalled === false);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
async function testMethodMismatchAndMissing() {
|
|
391
|
+
var key = _ecPem();
|
|
392
|
+
var mw = b.middleware.dpop({ replayStore: _ns(), getHtu: function () { return HTU; } });
|
|
393
|
+
|
|
394
|
+
// Proof built for POST, request is GET → htm mismatch → 401.
|
|
395
|
+
var proof = await _proof(key);
|
|
396
|
+
var rMis = await _call(mw, _req({ method: "GET", headers: { dpop: proof } }));
|
|
397
|
+
check("htm mismatch: POST proof on a GET request is refused", rMis.status === 401 && rMis.nextCalled === false);
|
|
398
|
+
|
|
399
|
+
// Missing method → htm "" → verify rejects a bad htm → 401 (fail closed).
|
|
400
|
+
var proof2 = await _proof(key, { jti: "jti-nomethod-1" });
|
|
401
|
+
var noMethodReq = b.testing.mockReq({ url: "/resource", headers: { host: "api.example.com", dpop: proof2 }, socket: { encrypted: true } });
|
|
402
|
+
noMethodReq.method = "";
|
|
403
|
+
var rNo = await _call(mw, noMethodReq);
|
|
404
|
+
check("htm missing: empty method is refused (401)", rNo.status === 401 && rNo.nextCalled === false);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// ---- algorithm allowlist + iat freshness enforced at the middleware ----
|
|
408
|
+
|
|
409
|
+
async function testAlgorithmAllowlist() {
|
|
410
|
+
var key = _ecPem();
|
|
411
|
+
// Allow only EdDSA; an ES256 proof must be refused (alg not in the list).
|
|
412
|
+
var mw = b.middleware.dpop({
|
|
413
|
+
replayStore: _ns(),
|
|
414
|
+
algorithms: ["EdDSA"],
|
|
415
|
+
getHtu: function () { return HTU; },
|
|
416
|
+
});
|
|
417
|
+
var es256 = await _proof(key);
|
|
418
|
+
var r = await _call(mw, _req({ headers: { dpop: es256 } }));
|
|
419
|
+
check("algorithms: an ES256 proof outside the allowlist is refused", r.status === 401 && r.nextCalled === false);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
async function testIatWindow() {
|
|
423
|
+
var key = _ecPem();
|
|
424
|
+
var mw = b.middleware.dpop({
|
|
425
|
+
replayStore: _ns(),
|
|
426
|
+
iatWindowSec: 60,
|
|
427
|
+
getHtu: function () { return HTU; },
|
|
428
|
+
});
|
|
429
|
+
// A proof issued 1000s ago is outside a 60s window → 401.
|
|
430
|
+
var stale = await _proof(key, { iat: Math.floor(Date.now() / 1000) - 1000 });
|
|
431
|
+
var r = await _call(mw, _req({ headers: { dpop: stale } }));
|
|
432
|
+
check("iat window: a stale proof (iat far in the past) is refused", r.status === 401 && r.nextCalled === false);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// ---- DPoP header shape (RFC 9449 §4.1: exactly one proof per request) ----
|
|
436
|
+
|
|
437
|
+
async function testMissingHeaderNoNonce() {
|
|
438
|
+
var mw = b.middleware.dpop({ replayStore: _ns() });
|
|
439
|
+
var r = await _call(mw, _req()); // no dpop header
|
|
440
|
+
check("missing header: 401 invalid_dpop_proof (no nonce manager)",
|
|
441
|
+
r.status === 401 && /invalid_dpop_proof/.test(r.cap.body) && !r.cap.headers["dpop-nonce"]);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
async function testCommaJoinedProofsRefused() {
|
|
445
|
+
var key = _ecPem();
|
|
446
|
+
var mw = b.middleware.dpop({ replayStore: _ns(), getHtu: function () { return HTU; } });
|
|
447
|
+
var p1 = await _proof(key);
|
|
448
|
+
var p2 = await _proof(key, { jti: "jti-comma-2" });
|
|
449
|
+
var r = await _call(mw, _req({ headers: { dpop: p1 + "," + p2 } }));
|
|
450
|
+
check("comma-joined: two proofs in one header value are refused",
|
|
451
|
+
r.status === 401 && /multiple DPoP proofs/.test(r.cap.body) && r.nextCalled === false);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
// RFC 9449 §4.1 — an array-valued DPoP header (more than one header line) must
|
|
455
|
+
// be refused AS a multiple-proof condition. The non-string guard used to shadow
|
|
456
|
+
// this branch, mislabeling it "DPoP header required"; the array case must reach
|
|
457
|
+
// its own diagnostic and never verify.
|
|
458
|
+
async function testArrayHeaderRefused() {
|
|
459
|
+
var mw = b.middleware.dpop({ replayStore: _ns(), getHtu: function () { return HTU; } });
|
|
460
|
+
var r = await _call(mw, _req({ headers: { dpop: ["proof-a", "proof-b"] } }));
|
|
461
|
+
check("array header: an array-valued DPoP header is refused (401)",
|
|
462
|
+
r.status === 401 && r.nextCalled === false);
|
|
463
|
+
check("array header: refusal reports the RFC 9449 §4.1 multiple-header condition",
|
|
464
|
+
/multiple DPoP headers/.test(r.cap.body));
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// ---- 401 response-shaping knobs ----
|
|
468
|
+
|
|
469
|
+
async function testOnDenyHook() {
|
|
470
|
+
var mw = b.middleware.dpop({
|
|
471
|
+
replayStore: _ns(),
|
|
472
|
+
getHtu: function () { return HTU; },
|
|
473
|
+
onDeny: function (req, res) { res.writeHead(499, { "content-type": "text/plain" }); res.end("owned"); },
|
|
474
|
+
});
|
|
475
|
+
var r = await _call(mw, _req()); // no proof → deny path → onDeny owns it
|
|
476
|
+
check("onDeny: the operator hook owns the refusal response", r.status === 499 && r.cap.body === "owned");
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
async function testProblemDetails() {
|
|
480
|
+
var mw = b.middleware.dpop({
|
|
481
|
+
replayStore: _ns(),
|
|
482
|
+
problemDetails: true,
|
|
483
|
+
getHtu: function () { return HTU; },
|
|
484
|
+
});
|
|
485
|
+
var r = await _call(mw, _req()); // no proof → deny path → problem+json
|
|
486
|
+
// problemDetails.respond writes res.statusCode directly (not via writeHead).
|
|
487
|
+
check("problemDetails: refusal is 401", r.res.statusCode === 401);
|
|
488
|
+
var ct = r.res.getHeader("content-type") || "";
|
|
489
|
+
check("problemDetails: content-type is application/problem+json", /problem\+json/.test(ct));
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
async function testAuditOffDoesNotThrow() {
|
|
493
|
+
var key = _ecPem();
|
|
494
|
+
var mw = b.middleware.dpop({
|
|
495
|
+
replayStore: _ns(),
|
|
496
|
+
audit: false,
|
|
497
|
+
getHtu: function () { return HTU; },
|
|
498
|
+
});
|
|
499
|
+
// Success path with audit off.
|
|
500
|
+
var good = await _proof(key);
|
|
501
|
+
var rOk = await _call(mw, _req({ headers: { dpop: good } }));
|
|
502
|
+
check("audit off: success path runs without emitting audit", rOk.nextCalled === true);
|
|
503
|
+
// Failure path with audit off.
|
|
504
|
+
var rBad = await _call(mw, _req({ headers: { dpop: "not-a-jwt" } }));
|
|
505
|
+
check("audit off: failure path refuses without emitting audit", rBad.status === 401 && rBad.nextCalled === false);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// ---- create()-time option refusals ----
|
|
509
|
+
|
|
510
|
+
function testCreateOptionRefusals() {
|
|
511
|
+
var threw1 = null;
|
|
512
|
+
try { b.middleware.dpop({ replayStore: _ns(), nonceStore: {} }); } catch (e) { threw1 = e; }
|
|
513
|
+
check("create: the obsolete nonceStore opt is refused", threw1 !== null && /nonceStore/.test(String(threw1.message || threw1)));
|
|
514
|
+
|
|
515
|
+
var threw2 = null;
|
|
516
|
+
try { b.middleware.dpop({ replayStore: _ns(), nonceWindowSec: 30 }); } catch (e) { threw2 = e; }
|
|
517
|
+
check("create: the obsolete nonceWindowSec opt is refused", threw2 !== null && /nonceWindowSec/.test(String(threw2.message || threw2)));
|
|
518
|
+
|
|
519
|
+
// Bad nonceRotateSec under requireNonce → throws at create().
|
|
520
|
+
var threw3 = null;
|
|
521
|
+
try { b.middleware.dpop({ replayStore: _ns(), requireNonce: true, nonceRotateSec: -5 }); } catch (e) { threw3 = e; }
|
|
522
|
+
check("create: a non-positive nonceRotateSec is refused under requireNonce", threw3 !== null);
|
|
523
|
+
|
|
524
|
+
// No-arg call: opts defaults to {} then the required replayStore is missing.
|
|
525
|
+
var threw4 = null;
|
|
526
|
+
try { b.middleware.dpop(); } catch (e) { threw4 = e; }
|
|
527
|
+
check("create: no-arg call fails closed on the missing replay store", threw4 !== null);
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
async function run() {
|
|
531
|
+
await testNonceChallengeAndAccept();
|
|
532
|
+
await testMalformedNonceClaimRefused();
|
|
533
|
+
await testNoncePreviousAcceptedAcrossRotation();
|
|
534
|
+
await testNonceManagerShutdown();
|
|
535
|
+
await testNonceManagerRevoke();
|
|
536
|
+
testLifecycleHooksNoopWithoutNonce();
|
|
537
|
+
await testAthBinding();
|
|
538
|
+
await testGetAccessTokenThrowSwallowed();
|
|
539
|
+
await testGetNonceCallback();
|
|
540
|
+
await testGetNonceNullAndThrow();
|
|
541
|
+
await testHtuReconstructStripsQueryAndFragment();
|
|
542
|
+
await testHtuCannotReconstruct();
|
|
543
|
+
await testMethodMismatchAndMissing();
|
|
544
|
+
await testAlgorithmAllowlist();
|
|
545
|
+
await testIatWindow();
|
|
546
|
+
await testMissingHeaderNoNonce();
|
|
547
|
+
await testCommaJoinedProofsRefused();
|
|
548
|
+
await testArrayHeaderRefused();
|
|
549
|
+
await testOnDenyHook();
|
|
550
|
+
await testProblemDetails();
|
|
551
|
+
await testAuditOffDoesNotThrow();
|
|
552
|
+
testCreateOptionRefusals();
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
module.exports = { run: run };
|
|
556
|
+
|
|
557
|
+
if (require.main === module) {
|
|
558
|
+
run().then(
|
|
559
|
+
function () { console.log("OK — " + helpers.getChecks() + " checks passed"); },
|
|
560
|
+
function (e) { console.error("FAIL:", e && e.stack || e); process.exit(1); }
|
|
561
|
+
);
|
|
562
|
+
}
|