@opensyber/tokenforge 0.1.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/LICENSE.md +32 -0
  2. package/README.md +205 -47
  3. package/dist/adapters/astro.d.ts +55 -0
  4. package/dist/adapters/astro.d.ts.map +1 -0
  5. package/dist/adapters/astro.js +91 -0
  6. package/dist/adapters/astro.js.map +1 -0
  7. package/dist/adapters/express.d.ts +15 -0
  8. package/dist/adapters/express.d.ts.map +1 -1
  9. package/dist/adapters/express.js +27 -0
  10. package/dist/adapters/express.js.map +1 -1
  11. package/dist/adapters/fastify.d.ts +17 -0
  12. package/dist/adapters/fastify.d.ts.map +1 -1
  13. package/dist/adapters/fastify.js +27 -0
  14. package/dist/adapters/fastify.js.map +1 -1
  15. package/dist/adapters/hono.d.ts +8 -4
  16. package/dist/adapters/hono.d.ts.map +1 -1
  17. package/dist/adapters/hono.js +7 -4
  18. package/dist/adapters/hono.js.map +1 -1
  19. package/dist/adapters/index.d.ts +5 -3
  20. package/dist/adapters/index.d.ts.map +1 -1
  21. package/dist/adapters/index.js +5 -3
  22. package/dist/adapters/index.js.map +1 -1
  23. package/dist/adapters/nextjs.d.ts +16 -0
  24. package/dist/adapters/nextjs.d.ts.map +1 -1
  25. package/dist/adapters/nextjs.js +26 -0
  26. package/dist/adapters/nextjs.js.map +1 -1
  27. package/dist/adapters/sveltekit.d.ts +57 -0
  28. package/dist/adapters/sveltekit.d.ts.map +1 -0
  29. package/dist/adapters/sveltekit.js +88 -0
  30. package/dist/adapters/sveltekit.js.map +1 -0
  31. package/dist/client/action-signer.d.ts +53 -0
  32. package/dist/client/action-signer.d.ts.map +1 -0
  33. package/dist/client/action-signer.js +48 -0
  34. package/dist/client/action-signer.js.map +1 -0
  35. package/dist/client/binding.d.ts +24 -7
  36. package/dist/client/binding.d.ts.map +1 -1
  37. package/dist/client/binding.js +17 -6
  38. package/dist/client/binding.js.map +1 -1
  39. package/dist/client/index.d.ts +13 -0
  40. package/dist/client/index.d.ts.map +1 -1
  41. package/dist/client/index.js +27 -1
  42. package/dist/client/index.js.map +1 -1
  43. package/dist/client/signer.d.ts +17 -0
  44. package/dist/client/signer.d.ts.map +1 -1
  45. package/dist/client/signer.js +23 -0
  46. package/dist/client/signer.js.map +1 -1
  47. package/dist/client/webauthn.d.ts +45 -0
  48. package/dist/client/webauthn.d.ts.map +1 -0
  49. package/dist/client/webauthn.js +118 -0
  50. package/dist/client/webauthn.js.map +1 -0
  51. package/dist/server/action-verify.d.ts +56 -0
  52. package/dist/server/action-verify.d.ts.map +1 -0
  53. package/dist/server/action-verify.js +47 -0
  54. package/dist/server/action-verify.js.map +1 -0
  55. package/dist/server/aitm-heuristics.d.ts +57 -0
  56. package/dist/server/aitm-heuristics.d.ts.map +1 -0
  57. package/dist/server/aitm-heuristics.js +120 -0
  58. package/dist/server/aitm-heuristics.js.map +1 -0
  59. package/dist/server/bound-cookie.d.ts +39 -0
  60. package/dist/server/bound-cookie.d.ts.map +1 -0
  61. package/dist/server/bound-cookie.js +59 -0
  62. package/dist/server/bound-cookie.js.map +1 -0
  63. package/dist/server/cbor.d.ts +20 -0
  64. package/dist/server/cbor.d.ts.map +1 -0
  65. package/dist/server/cbor.js +110 -0
  66. package/dist/server/cbor.js.map +1 -0
  67. package/dist/server/dbsc-challenge.d.ts +51 -0
  68. package/dist/server/dbsc-challenge.d.ts.map +1 -0
  69. package/dist/server/dbsc-challenge.js +78 -0
  70. package/dist/server/dbsc-challenge.js.map +1 -0
  71. package/dist/server/index.d.ts +2 -4
  72. package/dist/server/index.d.ts.map +1 -1
  73. package/dist/server/index.js +6 -4
  74. package/dist/server/index.js.map +1 -1
  75. package/dist/server/jws-verify.d.ts +46 -0
  76. package/dist/server/jws-verify.d.ts.map +1 -0
  77. package/dist/server/jws-verify.js +64 -0
  78. package/dist/server/jws-verify.js.map +1 -0
  79. package/dist/server/middleware.d.ts +15 -0
  80. package/dist/server/middleware.d.ts.map +1 -1
  81. package/dist/server/middleware.js +27 -0
  82. package/dist/server/middleware.js.map +1 -1
  83. package/dist/server/oidc-verify.d.ts +56 -0
  84. package/dist/server/oidc-verify.d.ts.map +1 -0
  85. package/dist/server/oidc-verify.js +107 -0
  86. package/dist/server/oidc-verify.js.map +1 -0
  87. package/dist/server/policy.d.ts +47 -0
  88. package/dist/server/policy.d.ts.map +1 -0
  89. package/dist/server/policy.js +84 -0
  90. package/dist/server/policy.js.map +1 -0
  91. package/dist/server/step-up-policy.d.ts +36 -0
  92. package/dist/server/step-up-policy.d.ts.map +1 -0
  93. package/dist/server/step-up-policy.js +101 -0
  94. package/dist/server/step-up-policy.js.map +1 -0
  95. package/dist/server/trust-score-fixtures.d.ts +9 -0
  96. package/dist/server/trust-score-fixtures.d.ts.map +1 -0
  97. package/dist/server/trust-score-fixtures.js +23 -0
  98. package/dist/server/trust-score-fixtures.js.map +1 -0
  99. package/dist/server/webauthn-verify.d.ts +41 -0
  100. package/dist/server/webauthn-verify.d.ts.map +1 -0
  101. package/dist/server/webauthn-verify.js +175 -0
  102. package/dist/server/webauthn-verify.js.map +1 -0
  103. package/dist/server/webauthn-verify.test-helpers.d.ts +8 -0
  104. package/dist/server/webauthn-verify.test-helpers.d.ts.map +1 -0
  105. package/dist/server/webauthn-verify.test-helpers.js +39 -0
  106. package/dist/server/webauthn-verify.test-helpers.js.map +1 -0
  107. package/dist/server/webhooks.d.ts +42 -0
  108. package/dist/server/webhooks.d.ts.map +1 -0
  109. package/dist/server/webhooks.js +77 -0
  110. package/dist/server/webhooks.js.map +1 -0
  111. package/dist/shared/action-hash.d.ts +23 -0
  112. package/dist/shared/action-hash.d.ts.map +1 -0
  113. package/dist/shared/action-hash.js +35 -0
  114. package/dist/shared/action-hash.js.map +1 -0
  115. package/dist/shared/types.d.ts +2 -0
  116. package/dist/shared/types.d.ts.map +1 -1
  117. package/dist/shared/types.js.map +1 -1
  118. package/package.json +44 -16
  119. package/dist/server/binding.d.ts +0 -19
  120. package/dist/server/binding.d.ts.map +0 -1
  121. package/dist/server/binding.js +0 -87
  122. package/dist/server/binding.js.map +0 -1
  123. package/dist/server/step-up.d.ts +0 -19
  124. package/dist/server/step-up.d.ts.map +0 -1
  125. package/dist/server/step-up.js +0 -139
  126. package/dist/server/step-up.js.map +0 -1
  127. package/dist/server/storage/index.d.ts +0 -3
  128. package/dist/server/storage/index.d.ts.map +0 -1
  129. package/dist/server/storage/index.js +0 -2
  130. package/dist/server/storage/index.js.map +0 -1
  131. package/dist/server/storage/interface.d.ts +0 -61
  132. package/dist/server/storage/interface.d.ts.map +0 -1
  133. package/dist/server/storage/interface.js +0 -2
  134. package/dist/server/storage/interface.js.map +0 -1
  135. package/dist/server/storage/memory.d.ts +0 -40
  136. package/dist/server/storage/memory.d.ts.map +0 -1
  137. package/dist/server/storage/memory.js +0 -107
  138. package/dist/server/storage/memory.js.map +0 -1
  139. package/dist/server/totp.d.ts +0 -53
  140. package/dist/server/totp.d.ts.map +0 -1
  141. package/dist/server/totp.js +0 -114
  142. package/dist/server/totp.js.map +0 -1
@@ -0,0 +1,175 @@
1
+ /**
2
+ * Server-side WebAuthn verifier — runs in Cloudflare Workers (Web Crypto only).
3
+ *
4
+ * Limitations (intentional, documented):
5
+ * - We use attestation: 'none' on the client, so attestation statement
6
+ * verification is skipped (only the authData → COSE_Key extraction matters).
7
+ * - Only ES256 (alg -7, ECDSA P-256) keys are accepted on the server. EdDSA
8
+ * is offered to the client for forward-compat but Web Crypto support is
9
+ * spotty in Workers; reject EdDSA at verify time with a clear error.
10
+ * - Counter check is not enforced here. Callers can read the 4-byte counter
11
+ * out of authenticatorData[33..37] if they want to persist + compare.
12
+ */
13
+ import { decodeCbor } from './cbor.js';
14
+ /** base64url → ArrayBuffer */
15
+ export function b64uToBuf(b64url) {
16
+ const base64 = b64url.replace(/-/g, '+').replace(/_/g, '/');
17
+ const padded = base64 + '='.repeat((4 - (base64.length % 4)) % 4);
18
+ const binary = atob(padded);
19
+ const bytes = new Uint8Array(binary.length);
20
+ for (let i = 0; i < binary.length; i++)
21
+ bytes[i] = binary.charCodeAt(i);
22
+ return bytes.buffer;
23
+ }
24
+ /** Uint8Array → base64url (no padding). */
25
+ export function bufToB64u(buf) {
26
+ const bytes = buf instanceof Uint8Array ? buf : new Uint8Array(buf);
27
+ let binary = '';
28
+ for (const byte of bytes)
29
+ binary += String.fromCharCode(byte);
30
+ return btoa(binary).replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
31
+ }
32
+ /** Parse clientDataJSON and verify challenge + origin. */
33
+ export function verifyClientDataJSON(clientDataJSON, expectedChallenge, expectedOrigin, expectedType) {
34
+ let json;
35
+ try {
36
+ const text = new TextDecoder().decode(b64uToBuf(clientDataJSON));
37
+ json = JSON.parse(text);
38
+ }
39
+ catch {
40
+ return { ok: false, reason: 'clientDataJSON malformed' };
41
+ }
42
+ if (json.type !== expectedType)
43
+ return { ok: false, reason: `type mismatch: ${json.type}` };
44
+ if (json.challenge !== expectedChallenge)
45
+ return { ok: false, reason: 'challenge mismatch' };
46
+ if (json.origin !== expectedOrigin)
47
+ return { ok: false, reason: `origin mismatch: ${json.origin}` };
48
+ return { ok: true };
49
+ }
50
+ /**
51
+ * Verify a WebAuthn attestation (registration). Returns the extracted
52
+ * public key as JWK plus the credentialId for persistence.
53
+ */
54
+ export async function verifyWebAuthnAttestation(attestationObjectB64u, clientDataJSONB64u, expectedChallenge, expectedOrigin) {
55
+ const cd = verifyClientDataJSON(clientDataJSONB64u, expectedChallenge, expectedOrigin, 'webauthn.create');
56
+ if (!cd.ok)
57
+ throw new Error(`webauthn.create: ${cd.reason}`);
58
+ const attBuf = new Uint8Array(b64uToBuf(attestationObjectB64u));
59
+ const decoded = decodeCbor(attBuf);
60
+ if (!(decoded instanceof Map))
61
+ throw new Error('attestationObject: not a CBOR map');
62
+ const authData = decoded.get('authData');
63
+ if (!(authData instanceof Uint8Array))
64
+ throw new Error('attestationObject: authData missing');
65
+ return parseAuthDataAttestedCredential(authData);
66
+ }
67
+ /** Pull rpIdHash + credentialId + COSE_Key out of attested authData. */
68
+ function parseAuthDataAttestedCredential(authData) {
69
+ if (authData.length < 37 + 18)
70
+ throw new Error('authData too short for attested credential');
71
+ const rpIdHash = authData.slice(0, 32);
72
+ const flags = authData[32] ?? 0;
73
+ if ((flags & 0x40) === 0)
74
+ throw new Error('authData: AT (attested credential) flag not set');
75
+ // skip signCount (4 bytes), aaguid (16 bytes)
76
+ let p = 37 + 16;
77
+ const credIdLen = ((authData[p] ?? 0) << 8) | (authData[p + 1] ?? 0);
78
+ p += 2;
79
+ const credentialId = authData.slice(p, p + credIdLen);
80
+ p += credIdLen;
81
+ const cosePublicKey = decodeCbor(authData.slice(p));
82
+ return { publicKeyJwk: coseToJwk(cosePublicKey), credentialId, rpIdHash };
83
+ }
84
+ /** Convert a COSE_Key (CBOR map) → JWK. ES256 only. */
85
+ function coseToJwk(cose) {
86
+ if (!(cose instanceof Map))
87
+ throw new Error('COSE_Key: not a map');
88
+ const kty = cose.get(1);
89
+ const alg = cose.get(3);
90
+ if (kty !== 2)
91
+ throw new Error(`COSE_Key kty=${String(kty)} unsupported (need EC2)`);
92
+ if (alg !== -7)
93
+ throw new Error(`COSE_Key alg=${String(alg)} unsupported (need ES256/-7)`);
94
+ const x = cose.get(-2);
95
+ const y = cose.get(-3);
96
+ if (!(x instanceof Uint8Array) || !(y instanceof Uint8Array)) {
97
+ throw new Error('COSE_Key: x/y missing');
98
+ }
99
+ return { kty: 'EC', crv: 'P-256', x: bufToB64u(x), y: bufToB64u(y) };
100
+ }
101
+ /**
102
+ * Verify a WebAuthn assertion. The signature is over
103
+ * (authenticatorData || sha256(clientDataJSON)).
104
+ */
105
+ export async function verifyWebAuthnAssertion(signatureB64u, authenticatorDataB64u, clientDataJSONB64u, publicKeyJwk, expectedChallenge, expectedOrigin) {
106
+ const cd = verifyClientDataJSON(clientDataJSONB64u, expectedChallenge, expectedOrigin, 'webauthn.get');
107
+ if (!cd.ok)
108
+ return false;
109
+ const authData = new Uint8Array(b64uToBuf(authenticatorDataB64u));
110
+ const clientDataBuf = new Uint8Array(b64uToBuf(clientDataJSONB64u));
111
+ const clientDataHash = new Uint8Array(await crypto.subtle.digest('SHA-256', clientDataBuf));
112
+ const signed = new Uint8Array(authData.length + clientDataHash.length);
113
+ signed.set(authData, 0);
114
+ signed.set(clientDataHash, authData.length);
115
+ const key = await crypto.subtle.importKey('jwk', publicKeyJwk, { name: 'ECDSA', namedCurve: 'P-256' }, false, ['verify']);
116
+ const sigDer = new Uint8Array(b64uToBuf(signatureB64u));
117
+ let sigRaw;
118
+ try {
119
+ sigRaw = derToRawEcdsa(sigDer);
120
+ }
121
+ catch {
122
+ return false;
123
+ }
124
+ try {
125
+ return await crypto.subtle.verify({ name: 'ECDSA', hash: { name: 'SHA-256' } }, key, copyToArrayBuffer(sigRaw), copyToArrayBuffer(signed));
126
+ }
127
+ catch {
128
+ return false;
129
+ }
130
+ }
131
+ /** Copy a Uint8Array into a freshly allocated ArrayBuffer (escapes SharedArrayBuffer typing). */
132
+ function copyToArrayBuffer(src) {
133
+ const out = new ArrayBuffer(src.byteLength);
134
+ new Uint8Array(out).set(src);
135
+ return out;
136
+ }
137
+ /** WebAuthn ECDSA sigs are DER-encoded; Web Crypto wants raw r||s. */
138
+ export function derToRawEcdsa(der) {
139
+ // SEQUENCE 0x30, total len, INTEGER 0x02, rLen, r, INTEGER 0x02, sLen, s
140
+ const at = (i) => {
141
+ const v = der[i];
142
+ if (v === undefined)
143
+ throw new Error('DER: truncated');
144
+ return v;
145
+ };
146
+ if (at(0) !== 0x30)
147
+ throw new Error('DER: not a SEQUENCE');
148
+ let p = 2;
149
+ if (at(1) & 0x80)
150
+ p = 2 + (at(1) & 0x7f);
151
+ if (at(p) !== 0x02)
152
+ throw new Error('DER: r not INTEGER');
153
+ let rLen = at(p + 1);
154
+ let rStart = p + 2;
155
+ if (rLen > 32) {
156
+ rStart += rLen - 32;
157
+ rLen = 32;
158
+ }
159
+ const r = der.slice(rStart, rStart + rLen);
160
+ p = rStart + rLen;
161
+ if (at(p) !== 0x02)
162
+ throw new Error('DER: s not INTEGER');
163
+ let sLen = at(p + 1);
164
+ let sStart = p + 2;
165
+ if (sLen > 32) {
166
+ sStart += sLen - 32;
167
+ sLen = 32;
168
+ }
169
+ const s = der.slice(sStart, sStart + sLen);
170
+ const raw = new Uint8Array(64);
171
+ raw.set(r, 32 - r.length);
172
+ raw.set(s, 64 - s.length);
173
+ return raw;
174
+ }
175
+ //# sourceMappingURL=webauthn-verify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webauthn-verify.js","sourceRoot":"","sources":["../../src/server/webauthn-verify.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Test-only helpers — inverse of derToRawEcdsa for synthesizing valid
3
+ * assertions in tests. NOT exported from the package.
4
+ */
5
+ export declare function makeP256Keypair(): Promise<CryptoKeyPair>;
6
+ /** Convert raw r||s ECDSA signature into the DER form WebAuthn produces. */
7
+ export declare function rawToDerEcdsa(raw: Uint8Array): Uint8Array;
8
+ //# sourceMappingURL=webauthn-verify.test-helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webauthn-verify.test-helpers.d.ts","sourceRoot":"","sources":["../../src/server/webauthn-verify.test-helpers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,wBAAsB,eAAe,IAAI,OAAO,CAAC,aAAa,CAAC,CAI9D;AAkBD,4EAA4E;AAC5E,wBAAgB,aAAa,CAAC,GAAG,EAAE,UAAU,GAAG,UAAU,CAYzD"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Test-only helpers — inverse of derToRawEcdsa for synthesizing valid
3
+ * assertions in tests. NOT exported from the package.
4
+ */
5
+ export async function makeP256Keypair() {
6
+ return crypto.subtle.generateKey({ name: 'ECDSA', namedCurve: 'P-256' }, true, ['sign', 'verify']);
7
+ }
8
+ function stripLeading(b) {
9
+ let i = 0;
10
+ while (i < b.length - 1 && b[i] === 0)
11
+ i++;
12
+ return b.slice(i);
13
+ }
14
+ function derInteger(b) {
15
+ const first = b[0] ?? 0;
16
+ const needsPad = first & 0x80;
17
+ const content = needsPad ? new Uint8Array([0x00, ...b]) : b;
18
+ const out = new Uint8Array(2 + content.length);
19
+ out[0] = 0x02;
20
+ out[1] = content.length;
21
+ out.set(content, 2);
22
+ return out;
23
+ }
24
+ /** Convert raw r||s ECDSA signature into the DER form WebAuthn produces. */
25
+ export function rawToDerEcdsa(raw) {
26
+ const r = stripLeading(raw.slice(0, 32));
27
+ const s = stripLeading(raw.slice(32, 64));
28
+ const rTLV = derInteger(r);
29
+ const sTLV = derInteger(s);
30
+ const body = new Uint8Array(rTLV.length + sTLV.length);
31
+ body.set(rTLV, 0);
32
+ body.set(sTLV, rTLV.length);
33
+ const out = new Uint8Array(2 + body.length);
34
+ out[0] = 0x30;
35
+ out[1] = body.length;
36
+ out.set(body, 2);
37
+ return out;
38
+ }
39
+ //# sourceMappingURL=webauthn-verify.test-helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webauthn-verify.test-helpers.js","sourceRoot":"","sources":["../../src/server/webauthn-verify.test-helpers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,OAAO,MAAM,CAAC,MAAM,CAAC,WAAW,CAC9B,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,CACjE,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,CAAa;IACjC,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QAAE,CAAC,EAAE,CAAC;IAC3C,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC;AAED,SAAS,UAAU,CAAC,CAAa;IAC/B,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACxB,MAAM,QAAQ,GAAG,KAAK,GAAG,IAAI,CAAC;IAC9B,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5D,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/C,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAAC,GAAG,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IACvC,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IACpB,OAAO,GAAG,CAAC;AACb,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,aAAa,CAAC,GAAe;IAC3C,MAAM,CAAC,GAAG,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IACzC,MAAM,CAAC,GAAG,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;IAC3B,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;IAC3B,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IACvD,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAClB,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5B,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5C,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;IACpC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACjB,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Webhook receiver helpers for TokenForge cloud deliveries.
3
+ *
4
+ * Every delivery carries three relevant headers:
5
+ * X-TF-Signature: "v1,<hex>" (one or more, space-separated during rotation)
6
+ * X-TF-Timestamp: ISO-8601 string — the moment dispatcher built the payload
7
+ * X-TF-Delivery-Id: UUID — per-attempt id, use for idempotency
8
+ *
9
+ * The signed string is `${timestamp}.${rawBody}` (no whitespace). During
10
+ * rotation, the dispatcher may send two `v1,<hex>` signatures — accept if
11
+ * either matches.
12
+ *
13
+ * Example (Node.js, Hono):
14
+ *
15
+ * import { verifyWebhookSignature } from '@opensyber/tokenforge/webhooks';
16
+ *
17
+ * app.post('/webhooks/tokenforge', async (c) => {
18
+ * const rawBody = await c.req.text();
19
+ * const ok = await verifyWebhookSignature({
20
+ * body: rawBody,
21
+ * signatureHeader: c.req.header('X-TF-Signature') ?? '',
22
+ * timestampHeader: c.req.header('X-TF-Timestamp') ?? '',
23
+ * secret: c.env.TOKENFORGE_WEBHOOK_SECRET,
24
+ * });
25
+ * if (!ok) return c.json({ error: 'bad_signature' }, 401);
26
+ * const event = JSON.parse(rawBody);
27
+ * // handle event.event, event.data ...
28
+ * return c.json({ received: true });
29
+ * });
30
+ */
31
+ export interface VerifyOptions {
32
+ body: string;
33
+ signatureHeader: string;
34
+ timestampHeader: string;
35
+ secret: string;
36
+ /** Max allowed clock skew in ms. Default 300000 (5 min). */
37
+ toleranceMs?: number;
38
+ /** Accept requests with missing timestamp (legacy). Default false. */
39
+ allowMissingTimestamp?: boolean;
40
+ }
41
+ export declare function verifyWebhookSignature(opts: VerifyOptions): Promise<boolean>;
42
+ //# sourceMappingURL=webhooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhooks.d.ts","sourceRoot":"","sources":["../../src/server/webhooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sEAAsE;IACtE,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,wBAAsB,sBAAsB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,CAyBlF"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Webhook receiver helpers for TokenForge cloud deliveries.
3
+ *
4
+ * Every delivery carries three relevant headers:
5
+ * X-TF-Signature: "v1,<hex>" (one or more, space-separated during rotation)
6
+ * X-TF-Timestamp: ISO-8601 string — the moment dispatcher built the payload
7
+ * X-TF-Delivery-Id: UUID — per-attempt id, use for idempotency
8
+ *
9
+ * The signed string is `${timestamp}.${rawBody}` (no whitespace). During
10
+ * rotation, the dispatcher may send two `v1,<hex>` signatures — accept if
11
+ * either matches.
12
+ *
13
+ * Example (Node.js, Hono):
14
+ *
15
+ * import { verifyWebhookSignature } from '@opensyber/tokenforge/webhooks';
16
+ *
17
+ * app.post('/webhooks/tokenforge', async (c) => {
18
+ * const rawBody = await c.req.text();
19
+ * const ok = await verifyWebhookSignature({
20
+ * body: rawBody,
21
+ * signatureHeader: c.req.header('X-TF-Signature') ?? '',
22
+ * timestampHeader: c.req.header('X-TF-Timestamp') ?? '',
23
+ * secret: c.env.TOKENFORGE_WEBHOOK_SECRET,
24
+ * });
25
+ * if (!ok) return c.json({ error: 'bad_signature' }, 401);
26
+ * const event = JSON.parse(rawBody);
27
+ * // handle event.event, event.data ...
28
+ * return c.json({ received: true });
29
+ * });
30
+ */
31
+ export async function verifyWebhookSignature(opts) {
32
+ const { body, signatureHeader, timestampHeader, secret } = opts;
33
+ const tolerance = opts.toleranceMs ?? 5 * 60_000;
34
+ if (!signatureHeader || !secret)
35
+ return false;
36
+ if (!timestampHeader) {
37
+ if (!opts.allowMissingTimestamp)
38
+ return false;
39
+ }
40
+ else {
41
+ const ts = Date.parse(timestampHeader);
42
+ if (Number.isNaN(ts))
43
+ return false;
44
+ if (Math.abs(Date.now() - ts) > tolerance)
45
+ return false;
46
+ }
47
+ const signedString = timestampHeader ? `${timestampHeader}.${body}` : body;
48
+ const expected = await hmacSha256Hex(secret, signedString);
49
+ // Signature header is space-separated list of "v1,<hex>" entries.
50
+ const entries = signatureHeader.split(/\s+/).filter(Boolean);
51
+ for (const entry of entries) {
52
+ const [version, hex] = entry.split(',');
53
+ if (version !== 'v1' || !hex)
54
+ continue;
55
+ if (timingSafeEqual(hex.toLowerCase(), expected))
56
+ return true;
57
+ }
58
+ return false;
59
+ }
60
+ function timingSafeEqual(a, b) {
61
+ if (a.length !== b.length)
62
+ return false;
63
+ let diff = 0;
64
+ for (let i = 0; i < a.length; i++)
65
+ diff |= a.charCodeAt(i) ^ b.charCodeAt(i);
66
+ return diff === 0;
67
+ }
68
+ async function hmacSha256Hex(secret, data) {
69
+ const key = await crypto.subtle.importKey('raw', new TextEncoder().encode(secret), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);
70
+ const sig = await crypto.subtle.sign('HMAC', key, new TextEncoder().encode(data));
71
+ const bytes = new Uint8Array(sig);
72
+ let hex = '';
73
+ for (let i = 0; i < bytes.length; i++)
74
+ hex += bytes[i].toString(16).padStart(2, '0');
75
+ return hex;
76
+ }
77
+ //# sourceMappingURL=webhooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhooks.js","sourceRoot":"","sources":["../../src/server/webhooks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Shared canonicalization + hash helper for action signing.
3
+ *
4
+ * Client (`client/action-signer.ts`) and server
5
+ * (`server/action-verify.ts`) MUST agree on these byte-for-byte;
6
+ * sharing this file is the simplest enforcement.
7
+ */
8
+ export interface ActionLikePayload {
9
+ action: string;
10
+ [key: string]: unknown;
11
+ }
12
+ /**
13
+ * Stable JSON serialization — sorts top-level keys so `{a:1,b:2}` and
14
+ * `{b:2,a:1}` produce the same string. JS object literals preserve
15
+ * insertion order, so without this two semantically-identical
16
+ * payloads from different code paths would hash differently and the
17
+ * server would reject one of them as a tamper.
18
+ */
19
+ export declare function canonicalizeAction(payload: Record<string, unknown>): string;
20
+ export declare function sha256B64Url(input: string): Promise<string>;
21
+ export declare function hashActionPayload(payload: Record<string, unknown>): Promise<string>;
22
+ export declare function b64UrlEncodeBytes(bytes: Uint8Array): string;
23
+ //# sourceMappingURL=action-hash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-hash.d.ts","sourceRoot":"","sources":["../../src/shared/action-hash.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAK3E;AAED,wBAAsB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGjE;AAED,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAEzF;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAI3D"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Shared canonicalization + hash helper for action signing.
3
+ *
4
+ * Client (`client/action-signer.ts`) and server
5
+ * (`server/action-verify.ts`) MUST agree on these byte-for-byte;
6
+ * sharing this file is the simplest enforcement.
7
+ */
8
+ /**
9
+ * Stable JSON serialization — sorts top-level keys so `{a:1,b:2}` and
10
+ * `{b:2,a:1}` produce the same string. JS object literals preserve
11
+ * insertion order, so without this two semantically-identical
12
+ * payloads from different code paths would hash differently and the
13
+ * server would reject one of them as a tamper.
14
+ */
15
+ export function canonicalizeAction(payload) {
16
+ const keys = Object.keys(payload).sort();
17
+ const ordered = {};
18
+ for (const k of keys)
19
+ ordered[k] = payload[k];
20
+ return JSON.stringify(ordered);
21
+ }
22
+ export async function sha256B64Url(input) {
23
+ const buf = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(input));
24
+ return b64UrlEncodeBytes(new Uint8Array(buf));
25
+ }
26
+ export async function hashActionPayload(payload) {
27
+ return sha256B64Url(canonicalizeAction(payload));
28
+ }
29
+ export function b64UrlEncodeBytes(bytes) {
30
+ let bin = '';
31
+ for (let i = 0; i < bytes.length; i++)
32
+ bin += String.fromCharCode(bytes[i]);
33
+ return btoa(bin).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
34
+ }
35
+ //# sourceMappingURL=action-hash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-hash.js","sourceRoot":"","sources":["../../src/shared/action-hash.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAgC;IACjE,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;IACzC,MAAM,OAAO,GAA4B,EAAE,CAAC;IAC5C,KAAK,MAAM,CAAC,IAAI,IAAI;QAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAC9C,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,KAAa;IAC9C,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACnF,OAAO,iBAAiB,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,OAAgC;IACtE,OAAO,YAAY,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAiB;IACjD,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,GAAG,IAAI,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC;IAC7E,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAC9E,CAAC"}
@@ -118,6 +118,8 @@ export interface ScoreBreakdown {
118
118
  velocityScore: number;
119
119
  timeScore: number;
120
120
  nonceScore: number;
121
+ /** Negative number — subtracted from total when AitM anomalies present. */
122
+ aitmDelta?: number;
121
123
  total: number;
122
124
  reasons: string[];
123
125
  }
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/shared/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/shared/types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/shared/types.ts"],"names":[],"mappings":"AAAA,kCAAkC;AAgKlC,2BAA2B;AAC3B,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,SAAS,EAAE,gBAAgB;IAC3B,KAAK,EAAE,YAAY;IACnB,SAAS,EAAE,gBAAgB;IAC3B,SAAS,EAAE,gBAAgB;CACnB,CAAC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/shared/types.ts"],"names":[],"mappings":"AAAA,kCAAkC;AAkKlC,2BAA2B;AAC3B,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,SAAS,EAAE,gBAAgB;IAC3B,KAAK,EAAE,YAAY;IACnB,SAAS,EAAE,gBAAgB;IAC3B,SAAS,EAAE,gBAAgB;CACnB,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@opensyber/tokenforge",
3
- "version": "0.1.1",
4
- "description": "Device-bound session security — ECDSA P-256 signatures for every request after login",
3
+ "version": "1.0.0",
4
+ "description": "Device-bound session security — W3C DBSC + ECDSA P-256 signatures + AitM detection. Drop-in for Auth0 / Okta / Clerk / Entra ID.",
5
5
  "private": false,
6
6
  "type": "module",
7
7
  "license": "SEE LICENSE IN LICENSE.md",
@@ -21,13 +21,16 @@
21
21
  "session-security",
22
22
  "tokenforge",
23
23
  "device-binding",
24
+ "dbsc",
24
25
  "ecdsa",
25
- "device-binding",
26
26
  "trust-score",
27
27
  "session-management",
28
28
  "web-crypto",
29
- "anti-session-hijacking"
29
+ "anti-session-hijacking",
30
+ "cookie-theft-protection",
31
+ "cisco-duo-alternative"
30
32
  ],
33
+ "sideEffects": false,
31
34
  "exports": {
32
35
  "./client": {
33
36
  "import": "./dist/client/index.js",
@@ -37,6 +40,22 @@
37
40
  "import": "./dist/server/index.js",
38
41
  "types": "./dist/server/index.d.ts"
39
42
  },
43
+ "./server/internal": {
44
+ "import": "./dist/server/internal.js",
45
+ "types": "./dist/server/internal.d.ts"
46
+ },
47
+ "./server/storage": {
48
+ "import": "./dist/server/storage/index.js",
49
+ "types": "./dist/server/storage/index.d.ts"
50
+ },
51
+ "./storage/internal": {
52
+ "import": "./dist/server/storage/internal.js",
53
+ "types": "./dist/server/storage/internal.d.ts"
54
+ },
55
+ "./webhooks": {
56
+ "import": "./dist/server/webhooks.js",
57
+ "types": "./dist/server/webhooks.d.ts"
58
+ },
40
59
  "./react": {
41
60
  "import": "./dist/react/index.js",
42
61
  "types": "./dist/react/index.d.ts"
@@ -61,17 +80,13 @@
61
80
  "import": "./dist/adapters/fastify.js",
62
81
  "types": "./dist/adapters/fastify.d.ts"
63
82
  },
64
- "./storage": {
65
- "import": "./dist/server/storage/index.js",
66
- "types": "./dist/server/storage/index.d.ts"
83
+ "./sveltekit": {
84
+ "import": "./dist/adapters/sveltekit.js",
85
+ "types": "./dist/adapters/sveltekit.d.ts"
67
86
  },
68
- "./storage/internal": {
69
- "import": "./src/server/storage/internal.ts",
70
- "types": "./src/server/storage/internal.ts"
71
- },
72
- "./server/internal": {
73
- "import": "./src/server/internal.ts",
74
- "types": "./src/server/internal.ts"
87
+ "./astro": {
88
+ "import": "./dist/adapters/astro.js",
89
+ "types": "./dist/adapters/astro.d.ts"
75
90
  }
76
91
  },
77
92
  "files": [
@@ -84,8 +99,12 @@
84
99
  "!dist/server/crypto.*",
85
100
  "!dist/server/trust-score.*",
86
101
  "!dist/server/verify.*",
102
+ "!dist/server/binding.*",
103
+ "!dist/server/step-up.*",
104
+ "!dist/server/totp.*",
87
105
  "!dist/server/middleware-internal.*",
88
106
  "!dist/server/internal.*",
107
+ "!dist/server/storage/**",
89
108
  "README.md",
90
109
  "LICENSE.md"
91
110
  ],
@@ -93,12 +112,15 @@
93
112
  "build": "tsc",
94
113
  "dev": "tsc --watch",
95
114
  "typecheck": "tsc --noEmit",
115
+ "lint": "eslint",
96
116
  "test": "vitest run",
117
+ "test:e2e": "playwright test",
118
+ "test:e2e:ui": "playwright test --ui",
97
119
  "clean": "rm -rf dist .turbo",
98
120
  "prepublishOnly": "pnpm run clean && pnpm run build"
99
121
  },
100
122
  "dependencies": {
101
- "hono": "^4.7.0"
123
+ "hono": "^4.12.14"
102
124
  },
103
125
  "peerDependencies": {
104
126
  "react": ">=18.0.0"
@@ -109,10 +131,16 @@
109
131
  }
110
132
  },
111
133
  "devDependencies": {
134
+ "@hono/node-server": "^1.19.13",
135
+ "@playwright/test": "^1.58.2",
136
+ "tsx": "^4.20.6",
112
137
  "@cloudflare/workers-types": "^4.20250214.0",
138
+ "@eslint/js": "^9.39.0",
113
139
  "@types/react": "^19.0.0",
140
+ "eslint": "^9",
114
141
  "react": "^19.0.0",
115
142
  "typescript": "^5.7.0",
116
- "vitest": "^3.0.0"
143
+ "typescript-eslint": "^8.0.0",
144
+ "vitest": "^4.0.0"
117
145
  }
118
146
  }
@@ -1,19 +0,0 @@
1
- import { Hono } from 'hono';
2
- import type { TokenForgeServerOptions } from '../shared/types.js';
3
- interface Variables {
4
- userId: string;
5
- sessionId: string;
6
- }
7
- /**
8
- * TokenForge binding and session management routes.
9
- * Mount at /api/tf on the main Hono app.
10
- * @param options - Server options (storage, thresholds, callbacks).
11
- * @returns A Hono sub-app with /bind, /sessions, /events, /trust-score routes.
12
- */
13
- export declare function createTokenForgeRoutes(options: TokenForgeServerOptions): Hono<{
14
- Variables: Variables;
15
- }>;
16
- /** @deprecated Use createTokenForgeRoutes(options) instead */
17
- export declare const tokenForgeRoutes: Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
18
- export {};
19
- //# sourceMappingURL=binding.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"binding.d.ts","sourceRoot":"","sources":["../../src/server/binding.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,uBAAuB,EAAiB,MAAM,oBAAoB,CAAC;AAEjF,UAAU,SAAS;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,uBAAuB,GAAG,IAAI,CAAC;IAAE,SAAS,EAAE,SAAS,CAAA;CAAE,CAAC,CAsFvG;AAED,8DAA8D;AAC9D,eAAO,MAAM,gBAAgB,4EAAa,CAAC"}