@atlasauth/emulator-core 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adopt.d.ts +50 -0
- package/dist/adopt.js +57 -0
- package/dist/adopt.js.map +1 -0
- package/dist/coverage.d.ts +15 -0
- package/dist/coverage.js +31 -0
- package/dist/coverage.js.map +1 -0
- package/dist/crypto-util.d.ts +10 -0
- package/dist/crypto-util.js +76 -0
- package/dist/crypto-util.js.map +1 -0
- package/dist/custom-html.d.ts +57 -0
- package/dist/custom-html.js +491 -0
- package/dist/custom-html.js.map +1 -0
- package/dist/engine.d.ts +34 -3
- package/dist/engine.js +57 -8
- package/dist/engine.js.map +1 -1
- package/dist/error-catalog.js +16 -0
- package/dist/error-catalog.js.map +1 -1
- package/dist/event-gate.d.ts +3 -0
- package/dist/event-gate.js +430 -0
- package/dist/event-gate.js.map +1 -0
- package/dist/generic.js +14 -2
- package/dist/generic.js.map +1 -1
- package/dist/handlers/access-signals.d.ts +48 -0
- package/dist/handlers/access-signals.js +76 -0
- package/dist/handlers/access-signals.js.map +1 -0
- package/dist/handlers/approvals.d.ts +2 -0
- package/dist/handlers/approvals.js +418 -0
- package/dist/handlers/approvals.js.map +1 -0
- package/dist/handlers/authz-data.d.ts +2 -0
- package/dist/handlers/authz-data.js +627 -0
- package/dist/handlers/authz-data.js.map +1 -0
- package/dist/handlers/authz-layers.d.ts +229 -0
- package/dist/handlers/authz-layers.js +786 -0
- package/dist/handlers/authz-layers.js.map +1 -0
- package/dist/handlers/authz-state.d.ts +80 -0
- package/dist/handlers/authz-state.js +175 -0
- package/dist/handlers/authz-state.js.map +1 -0
- package/dist/handlers/authz.d.ts +2 -0
- package/dist/handlers/authz.js +410 -0
- package/dist/handlers/authz.js.map +1 -0
- package/dist/handlers/billing.d.ts +100 -0
- package/dist/handlers/billing.js +877 -0
- package/dist/handlers/billing.js.map +1 -0
- package/dist/handlers/cedar-ext.d.ts +35 -0
- package/dist/handlers/cedar-ext.js +174 -0
- package/dist/handlers/cedar-ext.js.map +1 -0
- package/dist/handlers/cedar.d.ts +146 -0
- package/dist/handlers/cedar.js +689 -0
- package/dist/handlers/cedar.js.map +1 -0
- package/dist/handlers/connections.d.ts +5 -0
- package/dist/handlers/connections.js +561 -0
- package/dist/handlers/connections.js.map +1 -0
- package/dist/handlers/control.js +6 -1
- package/dist/handlers/control.js.map +1 -1
- package/dist/handlers/device.d.ts +47 -0
- package/dist/handlers/device.js +665 -0
- package/dist/handlers/device.js.map +1 -0
- package/dist/handlers/emu3-misc.d.ts +38 -0
- package/dist/handlers/emu3-misc.js +1056 -0
- package/dist/handlers/emu3-misc.js.map +1 -0
- package/dist/handlers/emu4-actions-access.d.ts +46 -0
- package/dist/handlers/emu4-actions-access.js +107 -0
- package/dist/handlers/emu4-actions-access.js.map +1 -0
- package/dist/handlers/emu4-actions-catalog-extra.d.ts +3 -0
- package/dist/handlers/emu4-actions-catalog-extra.js +204 -0
- package/dist/handlers/emu4-actions-catalog-extra.js.map +1 -0
- package/dist/handlers/emu4-actions-catalog.d.ts +3 -0
- package/dist/handlers/emu4-actions-catalog.js +143 -0
- package/dist/handlers/emu4-actions-catalog.js.map +1 -0
- package/dist/handlers/emu4-actions-def.d.ts +50 -0
- package/dist/handlers/emu4-actions-def.js +250 -0
- package/dist/handlers/emu4-actions-def.js.map +1 -0
- package/dist/handlers/emu4-actions-sandbox.d.ts +36 -0
- package/dist/handlers/emu4-actions-sandbox.js +318 -0
- package/dist/handlers/emu4-actions-sandbox.js.map +1 -0
- package/dist/handlers/emu4-actions-typegen.d.ts +5 -0
- package/dist/handlers/emu4-actions-typegen.js +73 -0
- package/dist/handlers/emu4-actions-typegen.js.map +1 -0
- package/dist/handlers/emu4-actions.d.ts +2 -0
- package/dist/handlers/emu4-actions.js +506 -0
- package/dist/handlers/emu4-actions.js.map +1 -0
- package/dist/handlers/emu4-authz-trust.d.ts +40 -0
- package/dist/handlers/emu4-authz-trust.js +488 -0
- package/dist/handlers/emu4-authz-trust.js.map +1 -0
- package/dist/handlers/emu4-authz.d.ts +2 -0
- package/dist/handlers/emu4-authz.js +752 -0
- package/dist/handlers/emu4-authz.js.map +1 -0
- package/dist/handlers/emu4-billing-core.d.ts +23 -0
- package/dist/handlers/emu4-billing-core.js +22 -0
- package/dist/handlers/emu4-billing-core.js.map +1 -0
- package/dist/handlers/emu4-billing-x.d.ts +2 -0
- package/dist/handlers/emu4-billing-x.js +489 -0
- package/dist/handlers/emu4-billing-x.js.map +1 -0
- package/dist/handlers/emu4-billing.d.ts +14 -0
- package/dist/handlers/emu4-billing.js +846 -0
- package/dist/handlers/emu4-billing.js.map +1 -0
- package/dist/handlers/emu4-clones.d.ts +2 -0
- package/dist/handlers/emu4-clones.js +322 -0
- package/dist/handlers/emu4-clones.js.map +1 -0
- package/dist/handlers/emu4-compliance.d.ts +8 -0
- package/dist/handlers/emu4-compliance.js +39 -0
- package/dist/handlers/emu4-compliance.js.map +1 -0
- package/dist/handlers/emu4-config.d.ts +14 -0
- package/dist/handlers/emu4-config.js +148 -0
- package/dist/handlers/emu4-config.js.map +1 -0
- package/dist/handlers/emu4-cookies.d.ts +8 -0
- package/dist/handlers/emu4-cookies.js +248 -0
- package/dist/handlers/emu4-cookies.js.map +1 -0
- package/dist/handlers/emu4-erasure.d.ts +2 -0
- package/dist/handlers/emu4-erasure.js +587 -0
- package/dist/handlers/emu4-erasure.js.map +1 -0
- package/dist/handlers/emu4-federation.d.ts +8 -0
- package/dist/handlers/emu4-federation.js +18 -0
- package/dist/handlers/emu4-federation.js.map +1 -0
- package/dist/handlers/emu4-journey-math.d.ts +42 -0
- package/dist/handlers/emu4-journey-math.js +99 -0
- package/dist/handlers/emu4-journey-math.js.map +1 -0
- package/dist/handlers/emu4-messaging.d.ts +21 -0
- package/dist/handlers/emu4-messaging.js +595 -0
- package/dist/handlers/emu4-messaging.js.map +1 -0
- package/dist/handlers/emu4-minors.d.ts +7 -0
- package/dist/handlers/emu4-minors.js +408 -0
- package/dist/handlers/emu4-minors.js.map +1 -0
- package/dist/handlers/emu4-oauth-audit.d.ts +5 -0
- package/dist/handlers/emu4-oauth-audit.js +17 -0
- package/dist/handlers/emu4-oauth-audit.js.map +1 -0
- package/dist/handlers/emu4-oauth-auth.d.ts +83 -0
- package/dist/handlers/emu4-oauth-auth.js +363 -0
- package/dist/handlers/emu4-oauth-auth.js.map +1 -0
- package/dist/handlers/emu4-oauth-delivery.d.ts +68 -0
- package/dist/handlers/emu4-oauth-delivery.js +207 -0
- package/dist/handlers/emu4-oauth-delivery.js.map +1 -0
- package/dist/handlers/emu4-oauth-keys.d.ts +11 -0
- package/dist/handlers/emu4-oauth-keys.js +268 -0
- package/dist/handlers/emu4-oauth-keys.js.map +1 -0
- package/dist/handlers/emu4-oauth-pub.d.ts +36 -0
- package/dist/handlers/emu4-oauth-pub.js +420 -0
- package/dist/handlers/emu4-oauth-pub.js.map +1 -0
- package/dist/handlers/emu4-oauth.d.ts +10 -0
- package/dist/handlers/emu4-oauth.js +23 -0
- package/dist/handlers/emu4-oauth.js.map +1 -0
- package/dist/handlers/emu4-policies.d.ts +2 -0
- package/dist/handlers/emu4-policies.js +408 -0
- package/dist/handlers/emu4-policies.js.map +1 -0
- package/dist/handlers/emu4-region.d.ts +2 -0
- package/dist/handlers/emu4-region.js +189 -0
- package/dist/handlers/emu4-region.js.map +1 -0
- package/dist/handlers/emu4-saml.d.ts +12 -0
- package/dist/handlers/emu4-saml.js +532 -0
- package/dist/handlers/emu4-saml.js.map +1 -0
- package/dist/handlers/emu4-shared.d.ts +44 -0
- package/dist/handlers/emu4-shared.js +90 -0
- package/dist/handlers/emu4-shared.js.map +1 -0
- package/dist/handlers/emu4-snapshots.d.ts +38 -0
- package/dist/handlers/emu4-snapshots.js +231 -0
- package/dist/handlers/emu4-snapshots.js.map +1 -0
- package/dist/handlers/emu4-sns.d.ts +9 -0
- package/dist/handlers/emu4-sns.js +21 -0
- package/dist/handlers/emu4-sns.js.map +1 -0
- package/dist/handlers/emu4-trust-binding.d.ts +27 -0
- package/dist/handlers/emu4-trust-binding.js +344 -0
- package/dist/handlers/emu4-trust-binding.js.map +1 -0
- package/dist/handlers/emu4-trust.d.ts +35 -0
- package/dist/handlers/emu4-trust.js +543 -0
- package/dist/handlers/emu4-trust.js.map +1 -0
- package/dist/handlers/federation.d.ts +2 -0
- package/dist/handlers/federation.js +481 -0
- package/dist/handlers/federation.js.map +1 -0
- package/dist/handlers/fga-engine.d.ts +78 -0
- package/dist/handlers/fga-engine.js +663 -0
- package/dist/handlers/fga-engine.js.map +1 -0
- package/dist/handlers/governance.d.ts +2 -0
- package/dist/handlers/governance.js +460 -0
- package/dist/handlers/governance.js.map +1 -0
- package/dist/handlers/hooks.js +17 -1
- package/dist/handlers/hooks.js.map +1 -1
- package/dist/handlers/index.d.ts +5 -1
- package/dist/handlers/index.js +45 -3
- package/dist/handlers/index.js.map +1 -1
- package/dist/handlers/keys.js +6 -1
- package/dist/handlers/keys.js.map +1 -1
- package/dist/handlers/machines.js +61 -8
- package/dist/handlers/machines.js.map +1 -1
- package/dist/handlers/messaging.d.ts +6 -0
- package/dist/handlers/messaging.js +893 -0
- package/dist/handlers/messaging.js.map +1 -0
- package/dist/handlers/oauth-adv.d.ts +191 -0
- package/dist/handlers/oauth-adv.js +1305 -0
- package/dist/handlers/oauth-adv.js.map +1 -0
- package/dist/handlers/oauth-flows.d.ts +52 -0
- package/dist/handlers/oauth-flows.js +480 -0
- package/dist/handlers/oauth-flows.js.map +1 -0
- package/dist/handlers/oauth.d.ts +96 -0
- package/dist/handlers/oauth.js +793 -0
- package/dist/handlers/oauth.js.map +1 -0
- package/dist/handlers/orgs.js +6 -0
- package/dist/handlers/orgs.js.map +1 -1
- package/dist/handlers/passkeys.d.ts +3 -0
- package/dist/handlers/passkeys.js +293 -0
- package/dist/handlers/passkeys.js.map +1 -0
- package/dist/handlers/platform.d.ts +20 -0
- package/dist/handlers/platform.js +472 -0
- package/dist/handlers/platform.js.map +1 -0
- package/dist/handlers/round2.d.ts +8 -0
- package/dist/handlers/round2.js +372 -0
- package/dist/handlers/round2.js.map +1 -0
- package/dist/handlers/scim.d.ts +4 -0
- package/dist/handlers/scim.js +595 -0
- package/dist/handlers/scim.js.map +1 -0
- package/dist/handlers/sessions.d.ts +9 -3
- package/dist/handlers/sessions.js +76 -38
- package/dist/handlers/sessions.js.map +1 -1
- package/dist/handlers/support.d.ts +20 -0
- package/dist/handlers/support.js +62 -0
- package/dist/handlers/support.js.map +1 -0
- package/dist/handlers/users.js +7 -0
- package/dist/handlers/users.js.map +1 -1
- package/dist/handlers/workflows.d.ts +2 -0
- package/dist/handlers/workflows.js +428 -0
- package/dist/handlers/workflows.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +23 -1
- package/dist/index.js.map +1 -1
- package/dist/jwe.d.ts +18 -0
- package/dist/jwe.js +101 -0
- package/dist/jwe.js.map +1 -0
- package/dist/jws.d.ts +41 -0
- package/dist/jws.js +135 -0
- package/dist/jws.js.map +1 -0
- package/dist/messages.d.ts +7 -0
- package/dist/messages.js +8 -4
- package/dist/messages.js.map +1 -1
- package/dist/messaging-callbacks.d.ts +100 -0
- package/dist/messaging-callbacks.js +767 -0
- package/dist/messaging-callbacks.js.map +1 -0
- package/dist/openapi.js +41 -1
- package/dist/openapi.js.map +1 -1
- package/dist/parity-bin.js +3 -1
- package/dist/parity-bin.js.map +1 -1
- package/dist/parity-emu3-authz.d.ts +3 -0
- package/dist/parity-emu3-authz.js +61 -0
- package/dist/parity-emu3-authz.js.map +1 -0
- package/dist/parity-emu3-billing.d.ts +3 -0
- package/dist/parity-emu3-billing.js +25 -0
- package/dist/parity-emu3-billing.js.map +1 -0
- package/dist/parity-emu3-messaging.d.ts +3 -0
- package/dist/parity-emu3-messaging.js +27 -0
- package/dist/parity-emu3-messaging.js.map +1 -0
- package/dist/parity-emu3-misc.d.ts +2 -0
- package/dist/parity-emu3-misc.js +63 -0
- package/dist/parity-emu3-misc.js.map +1 -0
- package/dist/parity-emu3-oauth.d.ts +2 -0
- package/dist/parity-emu3-oauth.js +39 -0
- package/dist/parity-emu3-oauth.js.map +1 -0
- package/dist/parity-emu4-actions.d.ts +2 -0
- package/dist/parity-emu4-actions.js +38 -0
- package/dist/parity-emu4-actions.js.map +1 -0
- package/dist/parity-emu4-authz.d.ts +3 -0
- package/dist/parity-emu4-authz.js +68 -0
- package/dist/parity-emu4-authz.js.map +1 -0
- package/dist/parity-emu4-billing.d.ts +6 -0
- package/dist/parity-emu4-billing.js +44 -0
- package/dist/parity-emu4-billing.js.map +1 -0
- package/dist/parity-emu4-compliance.d.ts +2 -0
- package/dist/parity-emu4-compliance.js +92 -0
- package/dist/parity-emu4-compliance.js.map +1 -0
- package/dist/parity-emu4-federation.d.ts +2 -0
- package/dist/parity-emu4-federation.js +33 -0
- package/dist/parity-emu4-federation.js.map +1 -0
- package/dist/parity-emu4-messaging.d.ts +3 -0
- package/dist/parity-emu4-messaging.js +42 -0
- package/dist/parity-emu4-messaging.js.map +1 -0
- package/dist/parity-emu4-oauth.d.ts +2 -0
- package/dist/parity-emu4-oauth.js +55 -0
- package/dist/parity-emu4-oauth.js.map +1 -0
- package/dist/parity-emu4-trust.d.ts +2 -0
- package/dist/parity-emu4-trust.js +41 -0
- package/dist/parity-emu4-trust.js.map +1 -0
- package/dist/parity-routes.d.ts +14 -0
- package/dist/parity-routes.js +439 -0
- package/dist/parity-routes.js.map +1 -0
- package/dist/parity.d.ts +10 -3
- package/dist/parity.js +14 -5
- package/dist/parity.js.map +1 -1
- package/dist/sns-cert.d.ts +9 -0
- package/dist/sns-cert.js +101 -0
- package/dist/sns-cert.js.map +1 -0
- package/dist/tokens.d.ts +85 -3
- package/dist/tokens.js +196 -24
- package/dist/tokens.js.map +1 -1
- package/dist/webauthn-virtual.d.ts +70 -0
- package/dist/webauthn-virtual.js +186 -0
- package/dist/webauthn-virtual.js.map +1 -0
- package/dist/webhook-ext.d.ts +16 -0
- package/dist/webhook-ext.js +218 -0
- package/dist/webhook-ext.js.map +1 -0
- package/dist/webhooks.d.ts +3 -0
- package/dist/webhooks.js +37 -3
- package/dist/webhooks.js.map +1 -1
- package/package.json +2 -2
package/dist/jwe.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isOpDecryptAlg = exports.JWE_ENCS = exports.OP_DECRYPT_ALGS = void 0;
|
|
4
|
+
exports.generateEncKey = generateEncKey;
|
|
5
|
+
exports.decryptJwe = decryptJwe;
|
|
6
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
7
|
+
const jws_1 = require("./jws");
|
|
8
|
+
/**
|
|
9
|
+
* Compact JWE decryption on Web Crypto only (like `jws.ts`), for request objects a client encrypts to the emulator's
|
|
10
|
+
* published encryption key: key management `RSA-OAEP-256` or `ECDH-ES` (P-256, direct), content encryption
|
|
11
|
+
* `A128GCM`, `A256GCM`, `A128CBC-HS256` or `A256CBC-HS512`. The same lists the real provider accepts.
|
|
12
|
+
*/
|
|
13
|
+
exports.OP_DECRYPT_ALGS = ['RSA-OAEP-256', 'ECDH-ES'];
|
|
14
|
+
exports.JWE_ENCS = ['A128GCM', 'A256GCM', 'A128CBC-HS256', 'A256CBC-HS512'];
|
|
15
|
+
const isOpDecryptAlg = (v) => exports.OP_DECRYPT_ALGS.includes(v);
|
|
16
|
+
exports.isOpDecryptAlg = isOpDecryptAlg;
|
|
17
|
+
async function generateEncKey(alg, kid) {
|
|
18
|
+
const pair = (await (alg === 'RSA-OAEP-256'
|
|
19
|
+
? crypto.subtle.generateKey({ name: 'RSA-OAEP', modulusLength: 2048, publicExponent: new Uint8Array([1, 0, 1]), hash: 'SHA-256' }, false, ['decrypt', 'encrypt'])
|
|
20
|
+
: crypto.subtle.generateKey({ name: 'ECDH', namedCurve: 'P-256' }, false, ['deriveBits'])));
|
|
21
|
+
const jwk = (await crypto.subtle.exportKey('jwk', pair.publicKey));
|
|
22
|
+
delete jwk.key_ops;
|
|
23
|
+
delete jwk.ext;
|
|
24
|
+
return { alg, kid, publicJwk: { ...jwk, kid, use: 'enc', alg }, privateKey: pair.privateKey };
|
|
25
|
+
}
|
|
26
|
+
const ENC_KEY_BYTES = { A128GCM: 16, A256GCM: 32, 'A128CBC-HS256': 32, 'A256CBC-HS512': 64 };
|
|
27
|
+
const u32 = (n) => new Uint8Array([(n >>> 24) & 255, (n >>> 16) & 255, (n >>> 8) & 255, n & 255]);
|
|
28
|
+
const cat = (...parts) => {
|
|
29
|
+
const out = new Uint8Array(parts.reduce((n, p) => n + p.length, 0));
|
|
30
|
+
let at = 0;
|
|
31
|
+
for (const p of parts)
|
|
32
|
+
(out.set(p, at), (at += p.length));
|
|
33
|
+
return out;
|
|
34
|
+
};
|
|
35
|
+
const lenPrefixed = (b) => cat(u32(b.length), b);
|
|
36
|
+
/** RFC 7518 section 4.6.2: the Concat KDF with SHA-256, `bits` of output. */
|
|
37
|
+
async function concatKdf(z, algId, apu, apv, bits) {
|
|
38
|
+
const info = cat(lenPrefixed(new TextEncoder().encode(algId)), lenPrefixed(apu), lenPrefixed(apv), u32(bits));
|
|
39
|
+
const rounds = Math.ceil(bits / 256);
|
|
40
|
+
const parts = [];
|
|
41
|
+
for (let i = 1; i <= rounds; i++)
|
|
42
|
+
parts.push(new Uint8Array(await crypto.subtle.digest('SHA-256', cat(u32(i), z, info))));
|
|
43
|
+
return cat(...parts).slice(0, bits / 8);
|
|
44
|
+
}
|
|
45
|
+
const tagEqual = (a, b) => {
|
|
46
|
+
if (a.length !== b.length)
|
|
47
|
+
return false;
|
|
48
|
+
let d = 0;
|
|
49
|
+
for (let i = 0; i < a.length; i++)
|
|
50
|
+
d |= a[i] ^ b[i];
|
|
51
|
+
return d === 0;
|
|
52
|
+
};
|
|
53
|
+
/** The plaintext of a compact JWE, or null when it is malformed, names another key, or fails authentication. Never throws. */
|
|
54
|
+
async function decryptJwe(jwe, key) {
|
|
55
|
+
try {
|
|
56
|
+
const parts = jwe.split('.');
|
|
57
|
+
if (parts.length !== 5)
|
|
58
|
+
return null;
|
|
59
|
+
const [h, ek, iv, ct, tag] = parts;
|
|
60
|
+
const header = JSON.parse(new TextDecoder().decode((0, jws_1.b64urlDecode)(h)));
|
|
61
|
+
const keyBytes = ENC_KEY_BYTES[header.enc];
|
|
62
|
+
if (header.alg !== key.alg || !keyBytes || header.zip !== undefined)
|
|
63
|
+
return null;
|
|
64
|
+
let cek;
|
|
65
|
+
if (key.alg === 'RSA-OAEP-256') {
|
|
66
|
+
cek = new Uint8Array(await crypto.subtle.decrypt({ name: 'RSA-OAEP' }, key.privateKey, (0, jws_1.b64urlDecode)(ek)));
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
const epk = header.epk;
|
|
70
|
+
if (ek || !epk || epk.kty !== 'EC' || epk.crv !== 'P-256')
|
|
71
|
+
return null;
|
|
72
|
+
const pub = await crypto.subtle.importKey('jwk', { kty: 'EC', crv: 'P-256', x: epk.x, y: epk.y }, { name: 'ECDH', namedCurve: 'P-256' }, false, []);
|
|
73
|
+
const z = new Uint8Array(await crypto.subtle.deriveBits({ name: 'ECDH', public: pub }, key.privateKey, 256));
|
|
74
|
+
cek = await concatKdf(z, header.enc, header.apu ? (0, jws_1.b64urlDecode)(header.apu) : new Uint8Array(), header.apv ? (0, jws_1.b64urlDecode)(header.apv) : new Uint8Array(), keyBytes * 8);
|
|
75
|
+
}
|
|
76
|
+
if (cek.length !== keyBytes)
|
|
77
|
+
return null;
|
|
78
|
+
const aad = new TextEncoder().encode(h);
|
|
79
|
+
const ivB = (0, jws_1.b64urlDecode)(iv);
|
|
80
|
+
const ctB = (0, jws_1.b64urlDecode)(ct);
|
|
81
|
+
const tagB = (0, jws_1.b64urlDecode)(tag);
|
|
82
|
+
if (header.enc.endsWith('GCM')) {
|
|
83
|
+
const k = await crypto.subtle.importKey('raw', cek, 'AES-GCM', false, ['decrypt']);
|
|
84
|
+
return new TextDecoder().decode(await crypto.subtle.decrypt({ name: 'AES-GCM', iv: ivB, additionalData: aad, tagLength: 128 }, k, cat(ctB, tagB)));
|
|
85
|
+
}
|
|
86
|
+
const half = keyBytes / 2;
|
|
87
|
+
const hash = header.enc === 'A128CBC-HS256' ? 'SHA-256' : 'SHA-512';
|
|
88
|
+
const mac = await crypto.subtle.importKey('raw', cek.slice(0, half), { name: 'HMAC', hash }, false, ['sign']);
|
|
89
|
+
const al = new Uint8Array(8);
|
|
90
|
+
new DataView(al.buffer).setUint32(4, aad.length * 8);
|
|
91
|
+
const expected = new Uint8Array(await crypto.subtle.sign('HMAC', mac, cat(aad, ivB, ctB, al))).slice(0, half);
|
|
92
|
+
if (!tagEqual(expected, tagB))
|
|
93
|
+
return null;
|
|
94
|
+
const k = await crypto.subtle.importKey('raw', cek.slice(half), 'AES-CBC', false, ['decrypt']);
|
|
95
|
+
return new TextDecoder().decode(await crypto.subtle.decrypt({ name: 'AES-CBC', iv: ivB }, k, ctB));
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=jwe.js.map
|
package/dist/jwe.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwe.js","sourceRoot":"","sources":["../src/jwe.ts"],"names":[],"mappings":"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"}
|
package/dist/jws.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/** JWS and DPoP helpers on Web Crypto only (no node:crypto), so the engine still runs in a browser worker. */
|
|
2
|
+
export declare const b64urlDecode: (s: string) => Uint8Array;
|
|
3
|
+
export interface DecodedJwt {
|
|
4
|
+
header: Record<string, any>;
|
|
5
|
+
payload: Record<string, any>;
|
|
6
|
+
signingInput: string;
|
|
7
|
+
signature: Uint8Array;
|
|
8
|
+
}
|
|
9
|
+
/** Split and parse a compact JWS; null when it is not one. Does not verify anything. */
|
|
10
|
+
export declare function decodeJwt(token: string): DecodedJwt | null;
|
|
11
|
+
export declare const SUPPORTED_ALGS: string[];
|
|
12
|
+
/** Verify a JWS signature with a public JWK. Never throws; a private-key JWK is refused. */
|
|
13
|
+
export declare function verifyJws(jwt: DecodedJwt, jwk: Record<string, any>): Promise<boolean>;
|
|
14
|
+
/** RFC 7638 thumbprint of a public JWK (base64url SHA-256); null for a key type the engine does not read. */
|
|
15
|
+
export declare function jwkThumbprintOf(jwk: Record<string, any>): Promise<string | null>;
|
|
16
|
+
/** `*` any run of characters, `?` one character; anchored. */
|
|
17
|
+
export declare const globMatch: (pattern: string, value: string) => boolean;
|
|
18
|
+
export declare const DPOP_IAT_WINDOW_S = 300;
|
|
19
|
+
export interface DpopCheck {
|
|
20
|
+
proof: string;
|
|
21
|
+
htm: string;
|
|
22
|
+
/** The URL the request was sent to; query and fragment are ignored (RFC 9449 section 4.3). */
|
|
23
|
+
htu: string;
|
|
24
|
+
nowMs: number;
|
|
25
|
+
/** When the proof accompanies an access token, the token it must hash (`ath`). */
|
|
26
|
+
accessToken?: string;
|
|
27
|
+
/** The server nonce the proof must carry, when one was issued. */
|
|
28
|
+
nonce?: string;
|
|
29
|
+
}
|
|
30
|
+
/** Validate a DPoP proof per RFC 9449. Returns the key thumbprint and jti, or throws Error(reason). Replay (jti) is the caller's. */
|
|
31
|
+
export declare function verifyDpopProof(c: DpopCheck): Promise<{
|
|
32
|
+
jkt: string;
|
|
33
|
+
jti: string;
|
|
34
|
+
iat: number;
|
|
35
|
+
}>;
|
|
36
|
+
/**
|
|
37
|
+
* The client certificate thumbprint (`x5t#S256`) a trusted edge forwarded, for mTLS binding. The emulator has no TLS, so
|
|
38
|
+
* it reads what a proxy would set: `x-client-cert` (PEM, optionally URL-encoded) or `x-client-cert-sha256` (the
|
|
39
|
+
* fingerprint, hex or base64url). Returns undefined when neither is present, null when one is present but unreadable.
|
|
40
|
+
*/
|
|
41
|
+
export declare function forwardedCertThumbprint(headers: Headers): Promise<string | undefined | null>;
|
package/dist/jws.js
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DPOP_IAT_WINDOW_S = exports.globMatch = exports.SUPPORTED_ALGS = exports.b64urlDecode = void 0;
|
|
4
|
+
exports.decodeJwt = decodeJwt;
|
|
5
|
+
exports.verifyJws = verifyJws;
|
|
6
|
+
exports.jwkThumbprintOf = jwkThumbprintOf;
|
|
7
|
+
exports.verifyDpopProof = verifyDpopProof;
|
|
8
|
+
exports.forwardedCertThumbprint = forwardedCertThumbprint;
|
|
9
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
10
|
+
const crypto_util_1 = require("./crypto-util");
|
|
11
|
+
/** JWS and DPoP helpers on Web Crypto only (no node:crypto), so the engine still runs in a browser worker. */
|
|
12
|
+
const b64urlDecode = (s) => {
|
|
13
|
+
const pad = s.replace(/-/g, '+').replace(/_/g, '/');
|
|
14
|
+
return Uint8Array.from(atob(pad + '='.repeat((4 - (pad.length % 4)) % 4)), (c) => c.charCodeAt(0));
|
|
15
|
+
};
|
|
16
|
+
exports.b64urlDecode = b64urlDecode;
|
|
17
|
+
const text = (s) => new TextDecoder().decode((0, exports.b64urlDecode)(s));
|
|
18
|
+
/** Split and parse a compact JWS; null when it is not one. Does not verify anything. */
|
|
19
|
+
function decodeJwt(token) {
|
|
20
|
+
const parts = token.split('.');
|
|
21
|
+
if (parts.length !== 3 || parts.some((p) => !p))
|
|
22
|
+
return null;
|
|
23
|
+
try {
|
|
24
|
+
const header = JSON.parse(text(parts[0]));
|
|
25
|
+
const payload = JSON.parse(text(parts[1]));
|
|
26
|
+
if (!header || typeof header !== 'object' || !payload || typeof payload !== 'object')
|
|
27
|
+
return null;
|
|
28
|
+
return { header, payload, signingInput: `${parts[0]}.${parts[1]}`, signature: (0, exports.b64urlDecode)(parts[2]) };
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const hashOf = (bits) => `SHA-${bits}`;
|
|
35
|
+
const ALGS = {
|
|
36
|
+
ES256: { import: { name: 'ECDSA', namedCurve: 'P-256' }, verify: { name: 'ECDSA', hash: hashOf('256') } },
|
|
37
|
+
ES384: { import: { name: 'ECDSA', namedCurve: 'P-384' }, verify: { name: 'ECDSA', hash: hashOf('384') } },
|
|
38
|
+
RS256: { import: { name: 'RSASSA-PKCS1-v1_5', hash: hashOf('256') }, verify: { name: 'RSASSA-PKCS1-v1_5' } },
|
|
39
|
+
RS384: { import: { name: 'RSASSA-PKCS1-v1_5', hash: hashOf('384') }, verify: { name: 'RSASSA-PKCS1-v1_5' } },
|
|
40
|
+
RS512: { import: { name: 'RSASSA-PKCS1-v1_5', hash: hashOf('512') }, verify: { name: 'RSASSA-PKCS1-v1_5' } },
|
|
41
|
+
ES512: { import: { name: 'ECDSA', namedCurve: 'P-521' }, verify: { name: 'ECDSA', hash: hashOf('512') } },
|
|
42
|
+
PS256: { import: { name: 'RSA-PSS', hash: hashOf('256') }, verify: { name: 'RSA-PSS', saltLength: 32 } },
|
|
43
|
+
PS384: { import: { name: 'RSA-PSS', hash: hashOf('384') }, verify: { name: 'RSA-PSS', saltLength: 48 } },
|
|
44
|
+
EdDSA: { import: { name: 'Ed25519' }, verify: { name: 'Ed25519' } },
|
|
45
|
+
};
|
|
46
|
+
exports.SUPPORTED_ALGS = Object.keys(ALGS);
|
|
47
|
+
/** Verify a JWS signature with a public JWK. Never throws; a private-key JWK is refused. */
|
|
48
|
+
async function verifyJws(jwt, jwk) {
|
|
49
|
+
const spec = ALGS[String(jwt.header.alg)];
|
|
50
|
+
if (!spec || 'd' in jwk || 'k' in jwk)
|
|
51
|
+
return false;
|
|
52
|
+
try {
|
|
53
|
+
const key = await crypto.subtle.importKey('jwk', { ...jwk, alg: undefined, use: undefined, key_ops: undefined }, spec.import, false, ['verify']);
|
|
54
|
+
return await crypto.subtle.verify(spec.verify, key, jwt.signature, new TextEncoder().encode(jwt.signingInput));
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const THUMB_KEYS = { EC: ['crv', 'kty', 'x', 'y'], RSA: ['e', 'kty', 'n'], OKP: ['crv', 'kty', 'x'] };
|
|
61
|
+
/** RFC 7638 thumbprint of a public JWK (base64url SHA-256); null for a key type the engine does not read. */
|
|
62
|
+
async function jwkThumbprintOf(jwk) {
|
|
63
|
+
const keys = THUMB_KEYS[String(jwk.kty)];
|
|
64
|
+
if (!keys || keys.some((k) => typeof jwk[k] !== 'string'))
|
|
65
|
+
return null;
|
|
66
|
+
return (0, crypto_util_1.bytesToB64url)(await (0, crypto_util_1.sha256)(JSON.stringify(Object.fromEntries(keys.map((k) => [k, jwk[k]])))));
|
|
67
|
+
}
|
|
68
|
+
/** `*` any run of characters, `?` one character; anchored. */
|
|
69
|
+
const globMatch = (pattern, value) => new RegExp(`^${pattern.replace(/[.+^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '.*').replace(/\?/g, '.')}$`, 's').test(value);
|
|
70
|
+
exports.globMatch = globMatch;
|
|
71
|
+
exports.DPOP_IAT_WINDOW_S = 300;
|
|
72
|
+
const stripUrl = (u) => {
|
|
73
|
+
const x = new URL(u);
|
|
74
|
+
return `${x.protocol}//${x.host}${x.pathname}`;
|
|
75
|
+
};
|
|
76
|
+
/** Validate a DPoP proof per RFC 9449. Returns the key thumbprint and jti, or throws Error(reason). Replay (jti) is the caller's. */
|
|
77
|
+
async function verifyDpopProof(c) {
|
|
78
|
+
const jwt = decodeJwt(c.proof);
|
|
79
|
+
if (!jwt)
|
|
80
|
+
throw new Error('The DPoP proof is not a JWT.');
|
|
81
|
+
const { header, payload } = jwt;
|
|
82
|
+
if (header.typ !== 'dpop+jwt')
|
|
83
|
+
throw new Error('The DPoP proof typ must be dpop+jwt.');
|
|
84
|
+
if (!(String(header.alg) in ALGS))
|
|
85
|
+
throw new Error('The DPoP proof alg is not an asymmetric algorithm this server accepts.');
|
|
86
|
+
const jwk = header.jwk;
|
|
87
|
+
if (!jwk || typeof jwk !== 'object' || 'd' in jwk)
|
|
88
|
+
throw new Error('The DPoP proof header must carry a public jwk.');
|
|
89
|
+
if (!(await verifyJws(jwt, jwk)))
|
|
90
|
+
throw new Error('The DPoP proof signature does not verify against its jwk.');
|
|
91
|
+
if (typeof payload.jti !== 'string' || !payload.jti)
|
|
92
|
+
throw new Error('The DPoP proof needs a jti.');
|
|
93
|
+
if (String(payload.htm).toUpperCase() !== c.htm.toUpperCase())
|
|
94
|
+
throw new Error('The DPoP proof htm does not match the request method.');
|
|
95
|
+
if (typeof payload.htu !== 'string' || stripUrl(payload.htu) !== stripUrl(c.htu))
|
|
96
|
+
throw new Error('The DPoP proof htu does not match the request URL.');
|
|
97
|
+
if (typeof payload.iat !== 'number' || Math.abs(c.nowMs / 1000 - payload.iat) > exports.DPOP_IAT_WINDOW_S)
|
|
98
|
+
throw new Error('The DPoP proof iat is outside the accepted window.');
|
|
99
|
+
if (c.nonce !== undefined && payload.nonce !== c.nonce)
|
|
100
|
+
throw new Error('The DPoP proof nonce is missing or wrong.');
|
|
101
|
+
if (c.accessToken !== undefined && payload.ath !== (0, crypto_util_1.bytesToB64url)(await (0, crypto_util_1.sha256)(c.accessToken)))
|
|
102
|
+
throw new Error('The DPoP proof ath does not match the access token.');
|
|
103
|
+
const jkt = await jwkThumbprintOf(jwk);
|
|
104
|
+
if (!jkt)
|
|
105
|
+
throw new Error('The DPoP proof jwk is not a key type this server reads.');
|
|
106
|
+
return { jkt, jti: payload.jti, iat: payload.iat };
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* The client certificate thumbprint (`x5t#S256`) a trusted edge forwarded, for mTLS binding. The emulator has no TLS, so
|
|
110
|
+
* it reads what a proxy would set: `x-client-cert` (PEM, optionally URL-encoded) or `x-client-cert-sha256` (the
|
|
111
|
+
* fingerprint, hex or base64url). Returns undefined when neither is present, null when one is present but unreadable.
|
|
112
|
+
*/
|
|
113
|
+
async function forwardedCertThumbprint(headers) {
|
|
114
|
+
const pem = headers.get('x-client-cert');
|
|
115
|
+
if (pem) {
|
|
116
|
+
try {
|
|
117
|
+
const body = decodeURIComponent(pem).replace(/-----[A-Z ]+-----/g, '').replace(/\s+/g, '');
|
|
118
|
+
const der = Uint8Array.from(atob(body), (ch) => ch.charCodeAt(0));
|
|
119
|
+
if (!der.length)
|
|
120
|
+
return null;
|
|
121
|
+
return (0, crypto_util_1.bytesToB64url)(await (0, crypto_util_1.sha256)(der));
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const fp = headers.get('x-client-cert-sha256');
|
|
128
|
+
if (!fp)
|
|
129
|
+
return undefined;
|
|
130
|
+
const hex = fp.replace(/:/g, '');
|
|
131
|
+
if (/^[0-9a-fA-F]{64}$/.test(hex))
|
|
132
|
+
return (0, crypto_util_1.bytesToB64url)(Uint8Array.from(hex.match(/../g).map((h) => parseInt(h, 16))));
|
|
133
|
+
return /^[A-Za-z0-9_-]{43}$/.test(fp) ? fp : null;
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=jws.js.map
|
package/dist/jws.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jws.js","sourceRoot":"","sources":["../src/jws.ts"],"names":[],"mappings":"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"}
|
package/dist/messages.d.ts
CHANGED
|
@@ -21,9 +21,16 @@ export interface MessageQuery {
|
|
|
21
21
|
* The universal message sink: everything the engine would have sent (email, SMS, WhatsApp, voice, push)
|
|
22
22
|
* lands here instead. Read it with `GET /__emulator/messages` or `engine.messages`.
|
|
23
23
|
*/
|
|
24
|
+
/** What the messaging layer decides for one outgoing message before it is sunk. `done` gets the sunk copy, or null when it was not delivered. */
|
|
25
|
+
export interface MessagePlan {
|
|
26
|
+
deliver: boolean;
|
|
27
|
+
done?: (sunk: SunkMessage | null) => void;
|
|
28
|
+
}
|
|
24
29
|
export declare class MessageSink {
|
|
25
30
|
private readonly clock;
|
|
26
31
|
readonly messages: SunkMessage[];
|
|
32
|
+
/** Suppression, provider failover and the message ledger plug in here (see handlers/messaging.ts); unset, every message is delivered. */
|
|
33
|
+
route?: (m: Omit<SunkMessage, 'id' | 'at'>) => MessagePlan;
|
|
27
34
|
private waiters;
|
|
28
35
|
constructor(clock: Clock);
|
|
29
36
|
send(m: Omit<SunkMessage, 'id' | 'at'>): SunkMessage;
|
package/dist/messages.js
CHANGED
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MessageSink = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* The universal message sink: everything the engine would have sent (email, SMS, WhatsApp, voice, push)
|
|
6
|
-
* lands here instead. Read it with `GET /__emulator/messages` or `engine.messages`.
|
|
7
|
-
*/
|
|
8
4
|
class MessageSink {
|
|
9
5
|
clock;
|
|
10
6
|
messages = [];
|
|
7
|
+
/** Suppression, provider failover and the message ledger plug in here (see handlers/messaging.ts); unset, every message is delivered. */
|
|
8
|
+
route;
|
|
11
9
|
waiters = [];
|
|
12
10
|
constructor(clock) {
|
|
13
11
|
this.clock = clock;
|
|
14
12
|
}
|
|
15
13
|
send(m) {
|
|
14
|
+
const plan = this.route?.(m);
|
|
15
|
+
if (plan && !plan.deliver) {
|
|
16
|
+
plan.done?.(null);
|
|
17
|
+
return { id: 0, at: new Date(this.clock.now()).toISOString(), ...m, meta: { ...(m.meta ?? {}), undelivered: true } };
|
|
18
|
+
}
|
|
16
19
|
const full = { id: this.messages.length + 1, at: new Date(this.clock.now()).toISOString(), ...m };
|
|
17
20
|
this.messages.push(full);
|
|
18
21
|
for (const w of [...this.waiters]) {
|
|
@@ -22,6 +25,7 @@ class MessageSink {
|
|
|
22
25
|
w.resolve(full);
|
|
23
26
|
}
|
|
24
27
|
}
|
|
28
|
+
plan?.done?.(full);
|
|
25
29
|
return full;
|
|
26
30
|
}
|
|
27
31
|
matches(m, q) {
|
package/dist/messages.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages.js","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"messages.js","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
export type EventStatus = 'sent' | 'delivered' | 'bounced' | 'complained' | 'failed';
|
|
2
|
+
export interface DeliveryEvent {
|
|
3
|
+
channel: 'email' | 'sms';
|
|
4
|
+
provider: string;
|
|
5
|
+
messageIds: string[];
|
|
6
|
+
status: EventStatus;
|
|
7
|
+
bounceType?: 'hard' | 'soft' | 'unknown';
|
|
8
|
+
recipient?: string;
|
|
9
|
+
detail?: string;
|
|
10
|
+
/** Epoch milliseconds. */
|
|
11
|
+
at: number;
|
|
12
|
+
suppress?: 'hard_bounce' | 'complaint' | 'unsubscribe' | 'invalid';
|
|
13
|
+
}
|
|
14
|
+
export declare const sha256Hex: (v: string | Uint8Array) => Promise<string>;
|
|
15
|
+
export interface TestKeys {
|
|
16
|
+
ec(): Promise<{
|
|
17
|
+
publicB64: string;
|
|
18
|
+
privateKey: CryptoKey;
|
|
19
|
+
}>;
|
|
20
|
+
rsa(): Promise<{
|
|
21
|
+
publicB64: string;
|
|
22
|
+
pkcs8: Uint8Array;
|
|
23
|
+
certPem: string;
|
|
24
|
+
}>;
|
|
25
|
+
}
|
|
26
|
+
export declare function testKeys(): TestKeys;
|
|
27
|
+
/** The test signing secret the emulator uses for a provider when none was stored (stable per instance). */
|
|
28
|
+
export declare function testSecret(instanceId: string, provider: string): Promise<string>;
|
|
29
|
+
/** The URL token of the providers that cannot sign (and the fallback when no signing secret is stored). */
|
|
30
|
+
export declare const receiverToken: (instanceId: string, provider: string) => Promise<string>;
|
|
31
|
+
export declare function idVariants(id: unknown): string[];
|
|
32
|
+
export declare function verifySvix(i: {
|
|
33
|
+
secret: string;
|
|
34
|
+
id: string;
|
|
35
|
+
timestamp: string;
|
|
36
|
+
signatureHeader: string;
|
|
37
|
+
body: string;
|
|
38
|
+
now: number;
|
|
39
|
+
}): Promise<boolean>;
|
|
40
|
+
export declare function snsStringToSign(m: Record<string, unknown>): string | null;
|
|
41
|
+
/** Where the emulator's SNS signing key is "served"; any other SNS host fails like an unreachable certificate. */
|
|
42
|
+
export declare const SNS_CERT_URL = "https://sns.us-east-1.amazonaws.com/SimpleNotificationService-emulator.pem";
|
|
43
|
+
export declare function presentedTokens(headers: Headers, query: Record<string, string>): string[];
|
|
44
|
+
export interface CallbackIn {
|
|
45
|
+
provider: string;
|
|
46
|
+
raw: string;
|
|
47
|
+
contentType: string;
|
|
48
|
+
headers: Headers;
|
|
49
|
+
query: Record<string, string>;
|
|
50
|
+
/** Every public URL the sender could have signed (Twilio signs the URL). */
|
|
51
|
+
urls: string[];
|
|
52
|
+
/** The stored verification secret (signing key, public key, whsec_, topic ARNs), or null. */
|
|
53
|
+
secret: string | null;
|
|
54
|
+
token: string;
|
|
55
|
+
/** Auth tokens of the instance's Twilio SMS providers. */
|
|
56
|
+
twilioTokens: string[];
|
|
57
|
+
/** The certificate (PEM) an SNS `SigningCertURL` serves, or null when nothing is served there. */
|
|
58
|
+
snsCertificate: (url: string) => Promise<string | null>;
|
|
59
|
+
/** Epoch seconds. */
|
|
60
|
+
now: number;
|
|
61
|
+
}
|
|
62
|
+
export type CallbackOut = {
|
|
63
|
+
ok: false;
|
|
64
|
+
why: string;
|
|
65
|
+
malformed?: boolean;
|
|
66
|
+
message?: string;
|
|
67
|
+
} | {
|
|
68
|
+
ok: true;
|
|
69
|
+
events: DeliveryEvent[];
|
|
70
|
+
id: string;
|
|
71
|
+
confirmed?: boolean;
|
|
72
|
+
subscribeUrl?: string;
|
|
73
|
+
};
|
|
74
|
+
/** Verify one callback with the provider's own scheme and say what it reports. Never throws. */
|
|
75
|
+
export declare function verifyCallback(i: CallbackIn): Promise<CallbackOut>;
|
|
76
|
+
export interface PrepIn {
|
|
77
|
+
provider: string;
|
|
78
|
+
event: EventStatus;
|
|
79
|
+
bounce: 'hard' | 'soft';
|
|
80
|
+
messageId: string;
|
|
81
|
+
recipient: string;
|
|
82
|
+
detail?: string;
|
|
83
|
+
/** The signing secret to use, or null for the URL-token mode of the providers that have one. */
|
|
84
|
+
secret: string | null;
|
|
85
|
+
token: string;
|
|
86
|
+
/** The public URL the callback is posted to, without a query. */
|
|
87
|
+
url: string;
|
|
88
|
+
now: number;
|
|
89
|
+
/** Appended to what is signed, so the signature is well formed but wrong (a tampered callback). */
|
|
90
|
+
salt: string;
|
|
91
|
+
topic: string;
|
|
92
|
+
keys: TestKeys;
|
|
93
|
+
}
|
|
94
|
+
export interface Prepared {
|
|
95
|
+
content_type: string;
|
|
96
|
+
body: string;
|
|
97
|
+
headers: Record<string, string>;
|
|
98
|
+
query: Record<string, string>;
|
|
99
|
+
}
|
|
100
|
+
export declare function prepareCallback(p: PrepIn): Promise<Prepared>;
|