dbsc-toolkit 2.10.0 → 2.12.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 (126) hide show
  1. package/README.md +43 -7
  2. package/dist/core/dpop/bind.d.ts +13 -0
  3. package/dist/core/dpop/bind.d.ts.map +1 -0
  4. package/dist/core/dpop/bind.js +12 -0
  5. package/dist/core/dpop/bind.js.map +1 -0
  6. package/dist/core/dpop/guard.d.ts +55 -0
  7. package/dist/core/dpop/guard.d.ts.map +1 -0
  8. package/dist/core/dpop/guard.js +40 -0
  9. package/dist/core/dpop/guard.js.map +1 -0
  10. package/dist/core/dpop/htu.d.ts +4 -0
  11. package/dist/core/dpop/htu.d.ts.map +1 -0
  12. package/dist/core/dpop/htu.js +42 -0
  13. package/dist/core/dpop/htu.js.map +1 -0
  14. package/dist/core/dpop/index.d.ts +9 -0
  15. package/dist/core/dpop/index.d.ts.map +1 -0
  16. package/dist/core/dpop/index.js +6 -0
  17. package/dist/core/dpop/index.js.map +1 -0
  18. package/dist/core/dpop/thumbprint.d.ts +13 -0
  19. package/dist/core/dpop/thumbprint.d.ts.map +1 -0
  20. package/dist/core/dpop/thumbprint.js +30 -0
  21. package/dist/core/dpop/thumbprint.js.map +1 -0
  22. package/dist/core/dpop/verify.d.ts +44 -0
  23. package/dist/core/dpop/verify.d.ts.map +1 -0
  24. package/dist/core/dpop/verify.js +124 -0
  25. package/dist/core/dpop/verify.js.map +1 -0
  26. package/dist/core/errors.d.ts +13 -0
  27. package/dist/core/errors.d.ts.map +1 -1
  28. package/dist/core/errors.js +16 -0
  29. package/dist/core/errors.js.map +1 -1
  30. package/dist/dpop/index.d.ts +12 -0
  31. package/dist/dpop/index.d.ts.map +1 -0
  32. package/dist/dpop/index.js +11 -0
  33. package/dist/dpop/index.js.map +1 -0
  34. package/dist/express/create-dbsc.d.ts +4 -1
  35. package/dist/express/create-dbsc.d.ts.map +1 -1
  36. package/dist/express/create-dbsc.js +2 -0
  37. package/dist/express/create-dbsc.js.map +1 -1
  38. package/dist/express/index.d.ts +1 -0
  39. package/dist/express/index.d.ts.map +1 -1
  40. package/dist/express/index.js +1 -0
  41. package/dist/express/index.js.map +1 -1
  42. package/dist/express/require-dpop.d.ts +17 -0
  43. package/dist/express/require-dpop.d.ts.map +1 -0
  44. package/dist/express/require-dpop.js +51 -0
  45. package/dist/express/require-dpop.js.map +1 -0
  46. package/dist/fastify/create-dbsc.d.ts +4 -0
  47. package/dist/fastify/create-dbsc.d.ts.map +1 -1
  48. package/dist/fastify/create-dbsc.js +2 -0
  49. package/dist/fastify/create-dbsc.js.map +1 -1
  50. package/dist/fastify/index.d.ts +1 -0
  51. package/dist/fastify/index.d.ts.map +1 -1
  52. package/dist/fastify/index.js +1 -0
  53. package/dist/fastify/index.js.map +1 -1
  54. package/dist/fastify/require-dpop.d.ts +13 -0
  55. package/dist/fastify/require-dpop.d.ts.map +1 -0
  56. package/dist/fastify/require-dpop.js +42 -0
  57. package/dist/fastify/require-dpop.js.map +1 -0
  58. package/dist/hono/create-dbsc.d.ts +3 -0
  59. package/dist/hono/create-dbsc.d.ts.map +1 -1
  60. package/dist/hono/create-dbsc.js +2 -0
  61. package/dist/hono/create-dbsc.js.map +1 -1
  62. package/dist/hono/index.d.ts +1 -0
  63. package/dist/hono/index.d.ts.map +1 -1
  64. package/dist/hono/index.js +1 -0
  65. package/dist/hono/index.js.map +1 -1
  66. package/dist/hono/require-dpop.d.ts +14 -0
  67. package/dist/hono/require-dpop.d.ts.map +1 -0
  68. package/dist/hono/require-dpop.js +38 -0
  69. package/dist/hono/require-dpop.js.map +1 -0
  70. package/dist/koa/create-dbsc.d.ts +28 -0
  71. package/dist/koa/create-dbsc.d.ts.map +1 -0
  72. package/dist/koa/create-dbsc.js +34 -0
  73. package/dist/koa/create-dbsc.js.map +1 -0
  74. package/dist/koa/index.d.ts +20 -0
  75. package/dist/koa/index.d.ts.map +1 -0
  76. package/dist/koa/index.js +27 -0
  77. package/dist/koa/index.js.map +1 -0
  78. package/dist/koa/require-dpop.d.ts +14 -0
  79. package/dist/koa/require-dpop.d.ts.map +1 -0
  80. package/dist/koa/require-dpop.js +38 -0
  81. package/dist/koa/require-dpop.js.map +1 -0
  82. package/dist/koa/require-proof.d.ts +9 -0
  83. package/dist/koa/require-proof.d.ts.map +1 -0
  84. package/dist/koa/require-proof.js +69 -0
  85. package/dist/koa/require-proof.js.map +1 -0
  86. package/dist/nestjs/index.d.ts +57 -0
  87. package/dist/nestjs/index.d.ts.map +1 -0
  88. package/dist/nestjs/index.js +193 -0
  89. package/dist/nestjs/index.js.map +1 -0
  90. package/dist/nextjs/index.d.ts +2 -0
  91. package/dist/nextjs/index.d.ts.map +1 -1
  92. package/dist/nextjs/index.js +1 -0
  93. package/dist/nextjs/index.js.map +1 -1
  94. package/dist/nextjs/require-dpop.d.ts +21 -0
  95. package/dist/nextjs/require-dpop.d.ts.map +1 -0
  96. package/dist/nextjs/require-dpop.js +35 -0
  97. package/dist/nextjs/require-dpop.js.map +1 -0
  98. package/dist/node/create-dbsc.d.ts +33 -0
  99. package/dist/node/create-dbsc.d.ts.map +1 -0
  100. package/dist/node/create-dbsc.js +35 -0
  101. package/dist/node/create-dbsc.js.map +1 -0
  102. package/dist/node/index.d.ts +55 -0
  103. package/dist/node/index.d.ts.map +1 -0
  104. package/dist/node/index.js +413 -0
  105. package/dist/node/index.js.map +1 -0
  106. package/dist/node/require-dpop.d.ts +17 -0
  107. package/dist/node/require-dpop.d.ts.map +1 -0
  108. package/dist/node/require-dpop.js +49 -0
  109. package/dist/node/require-dpop.js.map +1 -0
  110. package/dist/node/require-proof.d.ts +17 -0
  111. package/dist/node/require-proof.d.ts.map +1 -0
  112. package/dist/node/require-proof.js +74 -0
  113. package/dist/node/require-proof.js.map +1 -0
  114. package/dist/sveltekit/index.d.ts +49 -0
  115. package/dist/sveltekit/index.d.ts.map +1 -0
  116. package/dist/sveltekit/index.js +319 -0
  117. package/dist/sveltekit/index.js.map +1 -0
  118. package/dist/sveltekit/require-dpop.d.ts +17 -0
  119. package/dist/sveltekit/require-dpop.d.ts.map +1 -0
  120. package/dist/sveltekit/require-dpop.js +48 -0
  121. package/dist/sveltekit/require-dpop.js.map +1 -0
  122. package/dist/sveltekit/require-proof.d.ts +15 -0
  123. package/dist/sveltekit/require-proof.d.ts.map +1 -0
  124. package/dist/sveltekit/require-proof.js +52 -0
  125. package/dist/sveltekit/require-proof.js.map +1 -0
  126. package/package.json +47 -2
@@ -0,0 +1,49 @@
1
+ import type { Handle, RequestEvent } from "@sveltejs/kit";
2
+ import { type DbscOptions, type StorageAdapter, type ProofReplayCache, type ProtectionTier, type SkippedEntry, type CookieScope } from "../core/index.js";
3
+ export { requireProof } from "./require-proof.js";
4
+ export { requireDpop } from "./require-dpop.js";
5
+ /** Internal carrier so `requireProof()` can reach storage without re-passing it. */
6
+ export interface DbscInternal {
7
+ storage: StorageAdapter;
8
+ secure: boolean;
9
+ boundEnabled: boolean;
10
+ replayCache?: ProofReplayCache;
11
+ }
12
+ export declare const DBSC_INTERNAL: unique symbol;
13
+ export interface DbscSvelteKitOptions extends DbscOptions {
14
+ secure?: boolean;
15
+ boundStatePath?: string;
16
+ boundChallengePath?: string;
17
+ boundRegistrationPath?: string;
18
+ boundRefreshPath?: string;
19
+ }
20
+ export interface DbscSvelteKitSession {
21
+ sessionId: string | null;
22
+ tier: ProtectionTier;
23
+ skipped: SkippedEntry[];
24
+ revoke: () => Promise<void>;
25
+ }
26
+ export interface BindSessionOptions {
27
+ userId: string;
28
+ secure?: boolean;
29
+ cookieScope?: CookieScope;
30
+ cookieDomain?: string;
31
+ registrationPath?: string;
32
+ registrationCookieTtl?: number;
33
+ sessionTtl?: number;
34
+ }
35
+ /**
36
+ * Start a binding from a SvelteKit action or `+server` handler. Sets the
37
+ * registration header + cookies on the event; return your own response after.
38
+ */
39
+ export declare function bindSession(event: RequestEvent, sessionId: string, storage: StorageAdapter, opts: BindSessionOptions): Promise<void>;
40
+ /**
41
+ * SvelteKit `handle` hook. Add it to `src/hooks.server.ts`:
42
+ *
43
+ * export const handle = dbscHandle({ storage });
44
+ *
45
+ * It answers the DBSC protocol routes itself and, for every other request,
46
+ * resolves the session onto `event.locals.dbsc`.
47
+ */
48
+ export declare function dbscHandle(opts: DbscSvelteKitOptions): Handle;
49
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sveltekit/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAsBL,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,WAAW,EACjB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,oFAAoF;AACpF,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,cAAc,CAAC;IACxB,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,gBAAgB,CAAC;CAChC;AACD,eAAO,MAAM,aAAa,EAAE,OAAO,MAAkD,CAAC;AActF,MAAM,WAAW,oBAAqB,SAAQ,WAAW;IACvD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B;AAqCD,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,IAAI,CAAC,CAiCf;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,oBAAoB,GAAG,MAAM,CAoP7D"}
@@ -0,0 +1,319 @@
1
+ import { handleRegistration, handleRefresh, handleBoundRegistration, handleBoundRefresh, issueChallenge, buildRegistrationHeader, buildChallengeHeader, parseSessionSkippedHeader, REGISTRATION_HEADER, CHALLENGE_HEADER, LEGACY_REGISTRATION_HEADER, LEGACY_CHALLENGE_HEADER, NoopRateLimiter, emit, maybeEmitPolyfillMissing, resolveCookieNames, resolveCookieScope, cookieAttributesString, DbscProtocolError, DbscVerificationError, ErrorCodes, } from "../core/index.js";
2
+ export { requireProof } from "./require-proof.js";
3
+ export { requireDpop } from "./require-dpop.js";
4
+ export const DBSC_INTERNAL = Symbol("dbsc-toolkit.sveltekit.internal");
5
+ const cookieNames = (s) => resolveCookieNames(s);
6
+ const DEFAULT_BOUND_TTL = 10 * 60 * 1000;
7
+ const DEFAULT_REG_TTL = 24 * 60 * 60 * 1000;
8
+ const DEFAULT_SESSION_TTL = 24 * 60 * 60 * 1000;
9
+ function serializeCookie(name, value, scope, maxAgeSec) {
10
+ const { domain } = resolveCookieScope(scope);
11
+ const parts = [`${name}=${value}`, "HttpOnly"];
12
+ if (scope.secure)
13
+ parts.push("Secure");
14
+ parts.push("SameSite=Lax", `Max-Age=${maxAgeSec}`, "Path=/");
15
+ if (domain)
16
+ parts.push(`Domain=${domain}`);
17
+ return parts.join("; ");
18
+ }
19
+ function jsonResponse(status, body, extra) {
20
+ const headers = new Headers({ "content-type": "application/json" });
21
+ for (const [k, v] of Object.entries(extra?.headers ?? {}))
22
+ headers.set(k, v);
23
+ for (const c of extra?.cookies ?? [])
24
+ headers.append("set-cookie", c);
25
+ return new Response(JSON.stringify(body), { status, headers });
26
+ }
27
+ function emptyResponse(status, extra) {
28
+ const headers = new Headers();
29
+ for (const [k, v] of Object.entries(extra?.headers ?? {}))
30
+ headers.set(k, v);
31
+ for (const c of extra?.cookies ?? [])
32
+ headers.append("set-cookie", c);
33
+ return new Response(null, { status, headers });
34
+ }
35
+ function clientIp(event) {
36
+ try {
37
+ return event.getClientAddress();
38
+ }
39
+ catch {
40
+ return "unknown";
41
+ }
42
+ }
43
+ /**
44
+ * Start a binding from a SvelteKit action or `+server` handler. Sets the
45
+ * registration header + cookies on the event; return your own response after.
46
+ */
47
+ export async function bindSession(event, sessionId, storage, opts) {
48
+ const secure = opts.secure ?? true;
49
+ const registrationPath = opts.registrationPath ?? "/dbsc/registration";
50
+ const regCookieTtl = opts.registrationCookieTtl ?? DEFAULT_REG_TTL;
51
+ const sessionTtl = opts.sessionTtl ?? DEFAULT_SESSION_TTL;
52
+ const scope = {
53
+ secure,
54
+ ...(opts.cookieScope !== undefined && { cookieScope: opts.cookieScope }),
55
+ ...(opts.cookieDomain !== undefined && { cookieDomain: opts.cookieDomain }),
56
+ };
57
+ const { domain } = resolveCookieScope(scope);
58
+ const COOKIES = cookieNames(scope);
59
+ const existing = await storage.getSession(sessionId);
60
+ const now = Date.now();
61
+ if (!existing) {
62
+ await storage.setSession({
63
+ id: sessionId,
64
+ userId: opts.userId,
65
+ tier: "none",
66
+ createdAt: now,
67
+ expiresAt: now + sessionTtl,
68
+ lastRefreshAt: 0,
69
+ });
70
+ }
71
+ const challenge = await issueChallenge(sessionId, storage);
72
+ const regHeader = buildRegistrationHeader({ registrationPath, challenge: challenge.jti, cookieName: COOKIES.bound });
73
+ event.setHeaders({ [REGISTRATION_HEADER]: regHeader, [LEGACY_REGISTRATION_HEADER]: regHeader });
74
+ const base = { httpOnly: true, secure, sameSite: "lax", path: "/", ...(domain !== undefined && { domain }) };
75
+ event.cookies.set(COOKIES.reg, sessionId, { ...base, maxAge: regCookieTtl / 1000 });
76
+ event.cookies.set(COOKIES.challenge, challenge.jti, { ...base, maxAge: 5 * 60 });
77
+ }
78
+ /**
79
+ * SvelteKit `handle` hook. Add it to `src/hooks.server.ts`:
80
+ *
81
+ * export const handle = dbscHandle({ storage });
82
+ *
83
+ * It answers the DBSC protocol routes itself and, for every other request,
84
+ * resolves the session onto `event.locals.dbsc`.
85
+ */
86
+ export function dbscHandle(opts) {
87
+ const { storage, registrationPath = "/dbsc/registration", refreshPath = "/dbsc/refresh", boundStatePath = "/dbsc-bound/state", boundChallengePath = "/dbsc-bound/challenge", boundRegistrationPath = "/dbsc-bound/registration", boundRefreshPath = "/dbsc-bound/refresh", bound = true, boundCookieTtl = DEFAULT_BOUND_TTL, refreshGraceMs = 30_000, rateLimiter = new NoopRateLimiter(), replayCache, onEvent, secure = true, cookieScope, cookieDomain, } = opts;
88
+ const scope = {
89
+ secure,
90
+ ...(cookieScope !== undefined && { cookieScope }),
91
+ ...(cookieDomain !== undefined && { cookieDomain }),
92
+ };
93
+ resolveCookieScope(scope);
94
+ const cookieAttrs = cookieAttributesString(scope);
95
+ const COOKIES = cookieNames(scope);
96
+ const polyfillMissingEmitted = new Set();
97
+ function configBody(sessionId, origin, refreshUrl) {
98
+ return {
99
+ session_identifier: sessionId,
100
+ refresh_url: refreshUrl,
101
+ scope: { origin, include_site: true, scope_specification: [] },
102
+ credentials: [{ type: "cookie", name: COOKIES.bound, attributes: cookieAttrs }],
103
+ };
104
+ }
105
+ function get(req, name) {
106
+ return req.headers.get(name) ?? undefined;
107
+ }
108
+ function readBoundSessionId(event) {
109
+ return event.cookies.get(COOKIES.bound) ?? event.cookies.get(COOKIES.reg);
110
+ }
111
+ function skippedFrom(req) {
112
+ return parseSessionSkippedHeader({
113
+ "secure-session-skipped": req.headers.get("secure-session-skipped") ?? undefined,
114
+ "sec-session-skipped": req.headers.get("sec-session-skipped") ?? undefined,
115
+ });
116
+ }
117
+ return async ({ event, resolve }) => {
118
+ const { request, url } = event;
119
+ const method = request.method;
120
+ const ip = clientIp(event);
121
+ if (method === "POST" && url.pathname === registrationPath) {
122
+ const sessionId = event.cookies.get(COOKIES.reg);
123
+ const expectedJti = event.cookies.get(COOKIES.challenge);
124
+ if (!sessionId || !expectedJti)
125
+ return jsonResponse(400, { error: "missing session or challenge cookie" });
126
+ if (!(await rateLimiter.checkRegistration(ip)))
127
+ return jsonResponse(429, { error: "rate limited" });
128
+ try {
129
+ await handleRegistration({ sessionId, secSessionResponseHeader: get(request, "secure-session-response") ?? get(request, "sec-session-response"), expectedJti }, storage);
130
+ emit(onEvent, { type: "registration", sessionId, tier: "dbsc", timestamp: Date.now(), algorithm: "ES256", ip });
131
+ return jsonResponse(200, configBody(sessionId, url.origin, refreshPath), {
132
+ cookies: [
133
+ serializeCookie(COOKIES.bound, sessionId, scope, boundCookieTtl / 1000),
134
+ serializeCookie(COOKIES.challenge, "", scope, 0),
135
+ ],
136
+ });
137
+ }
138
+ catch (err) {
139
+ await rateLimiter.recordFailure(ip, sessionId);
140
+ if (err instanceof DbscVerificationError || err instanceof DbscProtocolError) {
141
+ emit(onEvent, { type: "verification_failure", sessionId, tier: "dbsc", timestamp: Date.now(), reason: err.code, ip });
142
+ return jsonResponse(400, { error: err.message });
143
+ }
144
+ throw err;
145
+ }
146
+ }
147
+ if (method === "POST" && url.pathname === refreshPath) {
148
+ const sessionId = get(request, "sec-secure-session-id") ?? event.cookies.get(COOKIES.bound);
149
+ if (!sessionId)
150
+ return emptyResponse(403);
151
+ if (!(await rateLimiter.checkRefresh(ip, sessionId)))
152
+ return jsonResponse(429, { error: "rate limited" });
153
+ const responseHeader = get(request, "secure-session-response") ?? get(request, "sec-session-response");
154
+ const expectedJti = event.cookies.get(COOKIES.challenge);
155
+ if (!responseHeader || !expectedJti) {
156
+ const challenge = await issueChallenge(sessionId, storage);
157
+ return emptyResponse(403, {
158
+ headers: { [CHALLENGE_HEADER]: buildChallengeHeader(challenge.jti, sessionId), [LEGACY_CHALLENGE_HEADER]: buildChallengeHeader(challenge.jti, sessionId) },
159
+ cookies: [serializeCookie(COOKIES.challenge, challenge.jti, scope, 5 * 60)],
160
+ });
161
+ }
162
+ try {
163
+ await handleRefresh({ sessionId, secSessionResponseHeader: responseHeader, expectedJti }, storage);
164
+ emit(onEvent, { type: "refresh", sessionId, tier: "dbsc", timestamp: Date.now(), ip });
165
+ return jsonResponse(200, configBody(sessionId, url.origin, refreshPath), {
166
+ cookies: [serializeCookie(COOKIES.bound, sessionId, scope, boundCookieTtl / 1000), serializeCookie(COOKIES.challenge, "", scope, 0)],
167
+ });
168
+ }
169
+ catch (err) {
170
+ await rateLimiter.recordFailure(ip, sessionId);
171
+ const stolenCheck = await storage.getBoundKey(sessionId);
172
+ if (stolenCheck && err instanceof DbscVerificationError && err.code === ErrorCodes.SIGNATURE_INVALID) {
173
+ emit(onEvent, { type: "session_stolen", sessionId, tier: "dbsc", timestamp: Date.now(), ip });
174
+ }
175
+ if (err instanceof DbscVerificationError || err instanceof DbscProtocolError) {
176
+ emit(onEvent, { type: "verification_failure", sessionId, tier: "dbsc", timestamp: Date.now(), reason: err.code, ip });
177
+ const challenge = await issueChallenge(sessionId, storage);
178
+ return jsonResponse(403, { error: err.message }, {
179
+ headers: { [CHALLENGE_HEADER]: buildChallengeHeader(challenge.jti, sessionId), [LEGACY_CHALLENGE_HEADER]: buildChallengeHeader(challenge.jti, sessionId) },
180
+ cookies: [serializeCookie(COOKIES.challenge, challenge.jti, scope, 5 * 60)],
181
+ });
182
+ }
183
+ throw err;
184
+ }
185
+ }
186
+ if (method === "GET" && url.pathname === boundStatePath) {
187
+ const headers = { "X-Server-Time": String(Date.now()) };
188
+ if (!bound)
189
+ return jsonResponse(200, { phase: "unbound", sessionId: null }, { headers });
190
+ const skipped = skippedFrom(request);
191
+ const nativeSkipped = skipped.length ? skipped.map((s) => s.reason) : undefined;
192
+ const sid = readBoundSessionId(event);
193
+ if (!sid)
194
+ return jsonResponse(200, { phase: "unbound", sessionId: null, ...(nativeSkipped && { nativeSkipped }) }, { headers });
195
+ const session = await storage.getSession(sid);
196
+ if (!session)
197
+ return jsonResponse(200, { phase: "unbound", sessionId: null, ...(nativeSkipped && { nativeSkipped }) }, { headers });
198
+ const nativeKey = await storage.getBoundKey(sid, "native");
199
+ const boundKey = await storage.getBoundKey(sid, "bound");
200
+ if (!nativeKey && !boundKey) {
201
+ const challenge = await issueChallenge(sid, storage);
202
+ return jsonResponse(200, { phase: "needs-registration", sessionId: sid, challenge: challenge.jti, ...(nativeSkipped && { nativeSkipped }) }, { headers });
203
+ }
204
+ if (nativeKey && !boundKey) {
205
+ const challenge = await issueChallenge(sid, storage);
206
+ return jsonResponse(200, { phase: "needs-bound-registration", sessionId: sid, tier: session.tier, challenge: challenge.jti, refreshIntervalMs: boundCookieTtl, ...(nativeSkipped && { nativeSkipped }) }, { headers });
207
+ }
208
+ return jsonResponse(200, { phase: "bound", sessionId: sid, tier: session.tier, refreshIntervalMs: boundCookieTtl, ...(nativeSkipped && { nativeSkipped }) }, { headers });
209
+ }
210
+ if (bound && method === "GET" && url.pathname === boundChallengePath) {
211
+ const headers = { "X-Server-Time": String(Date.now()) };
212
+ const sid = readBoundSessionId(event);
213
+ if (!sid)
214
+ return jsonResponse(403, { error: "no session" }, { headers });
215
+ const session = await storage.getSession(sid);
216
+ if (!session)
217
+ return jsonResponse(403, { error: "no session" }, { headers });
218
+ const challenge = await issueChallenge(sid, storage);
219
+ return jsonResponse(200, { challenge: challenge.jti }, { headers });
220
+ }
221
+ if (bound && method === "POST" && url.pathname === boundRegistrationPath) {
222
+ const headers = { "X-Server-Time": String(Date.now()) };
223
+ if (!(await rateLimiter.checkRegistration(ip)))
224
+ return jsonResponse(429, { error: "rate limited" }, { headers });
225
+ const sid = readBoundSessionId(event);
226
+ if (!sid)
227
+ return jsonResponse(400, { error: "missing session cookie" }, { headers });
228
+ let body;
229
+ try {
230
+ body = (await request.json()) ?? {};
231
+ }
232
+ catch {
233
+ return jsonResponse(400, { error: "body must be JSON" }, { headers });
234
+ }
235
+ if (!body.publicKey || !body.signature || !body.challenge)
236
+ return jsonResponse(400, { error: "publicKey, signature, and challenge are required" }, { headers });
237
+ try {
238
+ await handleBoundRegistration({ sessionId: sid, publicKey: body.publicKey, signature: body.signature, expectedJti: body.challenge }, storage);
239
+ emit(onEvent, { type: "registration", sessionId: sid, tier: "bound", timestamp: Date.now(), algorithm: "ES256", ip });
240
+ return jsonResponse(200, { session_identifier: sid, refresh_url: boundRefreshPath, tier: "bound" }, { headers, cookies: [serializeCookie(COOKIES.bound, sid, scope, boundCookieTtl / 1000)] });
241
+ }
242
+ catch (err) {
243
+ await rateLimiter.recordFailure(ip, sid);
244
+ if (err instanceof DbscVerificationError || err instanceof DbscProtocolError) {
245
+ emit(onEvent, { type: "verification_failure", sessionId: sid, tier: "bound", timestamp: Date.now(), reason: err.code, ip });
246
+ return jsonResponse(400, { error: err.message }, { headers });
247
+ }
248
+ throw err;
249
+ }
250
+ }
251
+ if (bound && method === "POST" && url.pathname === boundRefreshPath) {
252
+ const headers = { "X-Server-Time": String(Date.now()) };
253
+ const sid = readBoundSessionId(event);
254
+ if (!sid)
255
+ return jsonResponse(403, { error: "no session" }, { headers });
256
+ if (!(await rateLimiter.checkRefresh(ip, sid)))
257
+ return jsonResponse(429, { error: "rate limited" }, { headers });
258
+ let body;
259
+ try {
260
+ body = (await request.json()) ?? {};
261
+ }
262
+ catch {
263
+ return jsonResponse(400, { error: "body must be JSON" }, { headers });
264
+ }
265
+ if (!body.challenge || !body.signature || typeof body.timestamp !== "number")
266
+ return jsonResponse(400, { error: "challenge, signature, and timestamp are required" }, { headers });
267
+ try {
268
+ await handleBoundRefresh({ sessionId: sid, signature: body.signature, expectedJti: body.challenge, timestamp: body.timestamp }, storage);
269
+ emit(onEvent, { type: "refresh", sessionId: sid, tier: "bound", timestamp: Date.now(), ip });
270
+ return jsonResponse(200, { session_identifier: sid, refresh_url: boundRefreshPath, tier: "bound" }, { headers, cookies: [serializeCookie(COOKIES.bound, sid, scope, boundCookieTtl / 1000)] });
271
+ }
272
+ catch (err) {
273
+ await rateLimiter.recordFailure(ip, sid);
274
+ const keyStillThere = await storage.getBoundKey(sid);
275
+ if (keyStillThere && err instanceof DbscVerificationError && err.code === ErrorCodes.SIGNATURE_INVALID) {
276
+ emit(onEvent, { type: "session_stolen", sessionId: sid, tier: "bound", timestamp: Date.now(), ip });
277
+ }
278
+ if (err instanceof DbscVerificationError || err instanceof DbscProtocolError) {
279
+ emit(onEvent, { type: "verification_failure", sessionId: sid, tier: "bound", timestamp: Date.now(), reason: err.code, ip });
280
+ return jsonResponse(401, { error: err.message }, { headers });
281
+ }
282
+ throw err;
283
+ }
284
+ }
285
+ const sessionId = event.cookies.get(COOKIES.bound) ?? null;
286
+ const skipped = skippedFrom(request);
287
+ let tier = "none";
288
+ if (sessionId) {
289
+ const session = await storage.getSession(sessionId);
290
+ if (session) {
291
+ const staleAfter = session.lastRefreshAt + boundCookieTtl + refreshGraceMs;
292
+ const refreshable = session.tier === "dbsc" || session.tier === "bound";
293
+ tier = refreshable && Date.now() > staleAfter ? "none" : session.tier;
294
+ if (onEvent) {
295
+ await maybeEmitPolyfillMissing({ storage, session, ip, emitted: polyfillMissingEmitted, onEvent });
296
+ }
297
+ }
298
+ }
299
+ const dbscSession = {
300
+ sessionId,
301
+ tier,
302
+ skipped,
303
+ revoke: async () => {
304
+ if (sessionId)
305
+ await storage.revokeSession(sessionId);
306
+ event.cookies.delete(COOKIES.bound, { path: "/" });
307
+ },
308
+ };
309
+ dbscSession[DBSC_INTERNAL] = {
310
+ storage,
311
+ secure,
312
+ boundEnabled: bound,
313
+ ...(replayCache !== undefined && { replayCache }),
314
+ };
315
+ event.locals.dbsc = dbscSession;
316
+ return resolve(event);
317
+ };
318
+ }
319
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sveltekit/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { type RequestEvent } from "@sveltejs/kit";
2
+ import { type RequireDpopOptions } from "../core/dpop/index.js";
3
+ /**
4
+ * DPoP (RFC 9449) route guard for SvelteKit. Returns a 401 `Response` to return
5
+ * from the handler on failure, or `undefined` when the proof is valid:
6
+ *
7
+ * export async function GET(event) {
8
+ * const denied = await requireDpop({ getBoundJkt })(event);
9
+ * if (denied) return denied;
10
+ * // ... reached only with a valid DPoP proof
11
+ * }
12
+ *
13
+ * Unlike `requireProof` (which throws a 403), DPoP returns a Response so the
14
+ * `WWW-Authenticate: DPoP` header is carried per RFC 9449 §7.1.
15
+ */
16
+ export declare function requireDpop(opts?: RequireDpopOptions<RequestEvent>): (event: RequestEvent) => Promise<Response | undefined>;
17
+ //# sourceMappingURL=require-dpop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"require-dpop.d.ts","sourceRoot":"","sources":["../../src/sveltekit/require-dpop.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAGL,KAAK,kBAAkB,EACxB,MAAM,uBAAuB,CAAC;AAG/B;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,IAAI,GAAE,kBAAkB,CAAC,YAAY,CAAM,IACvD,OAAO,YAAY,KAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAqClE"}
@@ -0,0 +1,48 @@
1
+ import { runDpopGuard, DPOP_WWW_AUTHENTICATE, } from "../core/dpop/index.js";
2
+ import { DBSC_INTERNAL } from "./index.js";
3
+ /**
4
+ * DPoP (RFC 9449) route guard for SvelteKit. Returns a 401 `Response` to return
5
+ * from the handler on failure, or `undefined` when the proof is valid:
6
+ *
7
+ * export async function GET(event) {
8
+ * const denied = await requireDpop({ getBoundJkt })(event);
9
+ * if (denied) return denied;
10
+ * // ... reached only with a valid DPoP proof
11
+ * }
12
+ *
13
+ * Unlike `requireProof` (which throws a 403), DPoP returns a Response so the
14
+ * `WWW-Authenticate: DPoP` header is carried per RFC 9449 §7.1.
15
+ */
16
+ export function requireDpop(opts = {}) {
17
+ return async (event) => {
18
+ const session = event.locals.dbsc;
19
+ const internal = session
20
+ ? session[DBSC_INTERNAL]
21
+ : undefined;
22
+ const replayCache = opts.replayCache ?? internal?.replayCache;
23
+ const boundJkt = opts.getBoundJkt ? await opts.getBoundJkt(event) : undefined;
24
+ const outcome = await runDpopGuard({
25
+ proof: event.request.headers.get("DPoP") ?? undefined,
26
+ authorization: event.request.headers.get("Authorization") ?? undefined,
27
+ method: event.request.method,
28
+ url: event.url.href,
29
+ boundJkt,
30
+ replayCache,
31
+ opts: {
32
+ ...(opts.requireTokenBinding !== undefined && { requireTokenBinding: opts.requireTokenBinding }),
33
+ ...(opts.iatWindowMs !== undefined && { iatWindowMs: opts.iatWindowMs }),
34
+ },
35
+ });
36
+ if (!outcome.ok) {
37
+ return new Response(JSON.stringify({ error: "invalid_dpop_proof", code: outcome.error?.code }), {
38
+ status: 401,
39
+ headers: {
40
+ "Content-Type": "application/json",
41
+ "WWW-Authenticate": DPOP_WWW_AUTHENTICATE,
42
+ },
43
+ });
44
+ }
45
+ return undefined;
46
+ };
47
+ }
48
+ //# sourceMappingURL=require-dpop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"require-dpop.js","sourceRoot":"","sources":["../../src/sveltekit/require-dpop.ts"],"names":[],"mappings":"AACA,OAAO,EACL,YAAY,EACZ,qBAAqB,GAEtB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,aAAa,EAAgD,MAAM,YAAY,CAAC;AAEzF;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,WAAW,CAAC,OAAyC,EAAE;IACrE,OAAO,KAAK,EAAE,KAAmB,EAAiC,EAAE;QAClE,MAAM,OAAO,GAAI,KAAK,CAAC,MAAkC,CAAC,IAE7C,CAAC;QACd,MAAM,QAAQ,GAAG,OAAO;YACtB,CAAC,CAAG,OAAmD,CAAC,aAAa,CAA8B;YACnG,CAAC,CAAC,SAAS,CAAC;QACd,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,QAAQ,EAAE,WAAW,CAAC;QAC9D,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAE9E,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC;YACjC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,SAAS;YACrD,aAAa,EAAE,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,SAAS;YACtE,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM;YAC5B,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI;YACnB,QAAQ;YACR,WAAW;YACX,IAAI,EAAE;gBACJ,GAAG,CAAC,IAAI,CAAC,mBAAmB,KAAK,SAAS,IAAI,EAAE,mBAAmB,EAAE,IAAI,CAAC,mBAAmB,EAAE,CAAC;gBAChG,GAAG,CAAC,IAAI,CAAC,WAAW,KAAK,SAAS,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC;aACzE;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;YAChB,OAAO,IAAI,QAAQ,CACjB,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,oBAAoB,EAAE,IAAI,EAAE,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,EAC1E;gBACE,MAAM,EAAE,GAAG;gBACX,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,kBAAkB,EAAE,qBAAqB;iBAC1C;aACF,CACF,CAAC;QACJ,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { type RequestEvent } from "@sveltejs/kit";
2
+ import { type RequireProofOptions } from "../core/index.js";
3
+ /**
4
+ * The route guard for SvelteKit. `await` it at the top of a `+server` handler
5
+ * or a form action, after `dbscHandle` has populated `event.locals.dbsc`:
6
+ *
7
+ * export async function POST(event) {
8
+ * await requireProof()(event);
9
+ * // ... reached only from the bound device
10
+ * }
11
+ *
12
+ * Throws a SvelteKit `error(403)` when there is no binding or the proof fails.
13
+ */
14
+ export declare function requireProof(opts?: RequireProofOptions): (event: RequestEvent) => Promise<void>;
15
+ //# sourceMappingURL=require-proof.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"require-proof.d.ts","sourceRoot":"","sources":["../../src/sveltekit/require-proof.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,kBAAkB,CAAC;AAG1B;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,IAAI,GAAE,mBAAwB,IAC3C,OAAO,YAAY,KAAG,OAAO,CAAC,IAAI,CAAC,CAwClD"}
@@ -0,0 +1,52 @@
1
+ import { error } from "@sveltejs/kit";
2
+ import { verifyBoundProof, DbscVerificationError, } from "../core/index.js";
3
+ import { DBSC_INTERNAL } from "./index.js";
4
+ /**
5
+ * The route guard for SvelteKit. `await` it at the top of a `+server` handler
6
+ * or a form action, after `dbscHandle` has populated `event.locals.dbsc`:
7
+ *
8
+ * export async function POST(event) {
9
+ * await requireProof()(event);
10
+ * // ... reached only from the bound device
11
+ * }
12
+ *
13
+ * Throws a SvelteKit `error(403)` when there is no binding or the proof fails.
14
+ */
15
+ export function requireProof(opts = {}) {
16
+ return async (event) => {
17
+ const session = event.locals.dbsc;
18
+ const tier = session?.tier ?? "none";
19
+ if (!session?.sessionId || tier === "none") {
20
+ throw error(403, "device-bound session required");
21
+ }
22
+ const internal = session[DBSC_INTERNAL];
23
+ const storage = opts.storage ?? internal?.storage;
24
+ if (!storage) {
25
+ throw error(500, "requireProof: storage unavailable — add dbscHandle to hooks.server.ts, or pass { storage }");
26
+ }
27
+ const allowDbscWithoutProof = opts.allowDbscWithoutProof ?? (internal?.boundEnabled === false ? true : undefined);
28
+ if (tier === "dbsc" && allowDbscWithoutProof)
29
+ return;
30
+ const proofHeader = event.request.headers.get("x-dbsc-bound-proof") ?? undefined;
31
+ const bodyBytes = new Uint8Array(await event.request.clone().arrayBuffer());
32
+ try {
33
+ await verifyBoundProof({
34
+ sessionId: session.sessionId,
35
+ proofHeader,
36
+ method: event.request.method,
37
+ path: event.url.pathname,
38
+ signBody: true,
39
+ bodyBytes,
40
+ ...(opts.timestampWindowMs !== undefined && { timestampWindowMs: opts.timestampWindowMs }),
41
+ ...(internal?.replayCache !== undefined && { replayCache: internal.replayCache }),
42
+ }, storage);
43
+ }
44
+ catch (err) {
45
+ if (err instanceof DbscVerificationError) {
46
+ throw error(403, err.message);
47
+ }
48
+ throw err;
49
+ }
50
+ };
51
+ }
52
+ //# sourceMappingURL=require-proof.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"require-proof.js","sourceRoot":"","sources":["../../src/sveltekit/require-proof.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAqB,MAAM,eAAe,CAAC;AACzD,OAAO,EACL,gBAAgB,EAChB,qBAAqB,GAEtB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAgD,MAAM,YAAY,CAAC;AAEzF;;;;;;;;;;GAUG;AACH,MAAM,UAAU,YAAY,CAAC,OAA4B,EAAE;IACzD,OAAO,KAAK,EAAE,KAAmB,EAAiB,EAAE;QAClD,MAAM,OAAO,GAAI,KAAK,CAAC,MAAkC,CAAC,IAAwC,CAAC;QACnG,MAAM,IAAI,GAAG,OAAO,EAAE,IAAI,IAAI,MAAM,CAAC;QACrC,IAAI,CAAC,OAAO,EAAE,SAAS,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;YAC3C,MAAM,KAAK,CAAC,GAAG,EAAE,+BAA+B,CAAC,CAAC;QACpD,CAAC;QAED,MAAM,QAAQ,GAAI,OAAmD,CAAC,aAAa,CAA6B,CAAC;QACjH,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,QAAQ,EAAE,OAAO,CAAC;QAClD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,KAAK,CAAC,GAAG,EAAE,4FAA4F,CAAC,CAAC;QACjH,CAAC;QAED,MAAM,qBAAqB,GACzB,IAAI,CAAC,qBAAqB,IAAI,CAAC,QAAQ,EAAE,YAAY,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QACtF,IAAI,IAAI,KAAK,MAAM,IAAI,qBAAqB;YAAE,OAAO;QAErD,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,IAAI,SAAS,CAAC;QACjF,MAAM,SAAS,GAAG,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;QAC5E,IAAI,CAAC;YACH,MAAM,gBAAgB,CACpB;gBACE,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,WAAW;gBACX,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM;gBAC5B,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,QAAQ;gBACxB,QAAQ,EAAE,IAAI;gBACd,SAAS;gBACT,GAAG,CAAC,IAAI,CAAC,iBAAiB,KAAK,SAAS,IAAI,EAAE,iBAAiB,EAAE,IAAI,CAAC,iBAAiB,EAAE,CAAC;gBAC1F,GAAG,CAAC,QAAQ,EAAE,WAAW,KAAK,SAAS,IAAI,EAAE,WAAW,EAAE,QAAQ,CAAC,WAAW,EAAE,CAAC;aAClF,EACD,OAAO,CACR,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,qBAAqB,EAAE,CAAC;gBACzC,MAAM,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;YAChC,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}