@dbsc-toolkit/better-auth 0.1.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.
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Client plugin for @dbsc-toolkit/better-auth.
3
+ *
4
+ * Provides TypeScript inference for the DBSC endpoints so your
5
+ * Better Auth client knows about /dbsc/* and /dbsc-bound/* paths.
6
+ *
7
+ * Usage:
8
+ * import { createAuthClient } from "better-auth/client"
9
+ * import { dbscClient } from "@dbsc-toolkit/better-auth/client"
10
+ *
11
+ * export const authClient = createAuthClient({
12
+ * plugins: [dbscClient()]
13
+ * })
14
+ *
15
+ * Then initialize the polyfill in your browser entry point:
16
+ * import { initBoundDbsc } from "dbsc-toolkit/client"
17
+ * initBoundDbsc({ baseUrl: "" })
18
+ */
19
+ export declare function dbscClient(): {
20
+ id: string;
21
+ pathMethods: {
22
+ readonly "/dbsc/registration": "POST";
23
+ readonly "/dbsc/refresh": "POST";
24
+ readonly "/dbsc-bound/state": "GET";
25
+ readonly "/dbsc-bound/challenge": "GET";
26
+ readonly "/dbsc-bound/registration": "POST";
27
+ readonly "/dbsc-bound/refresh": "POST";
28
+ };
29
+ getActions(fetch: (path: string, options?: RequestInit) => Promise<Response>): {
30
+ dbsc: {
31
+ /** Check bound state for the current session. */
32
+ getBoundState: () => Promise<Response>;
33
+ /** Manually trigger polyfill registration (normally automatic). */
34
+ registerBound: (body: {
35
+ sessionId: string;
36
+ jwk: JsonWebKey;
37
+ challenge: string;
38
+ }) => Promise<Response>;
39
+ };
40
+ };
41
+ getAtoms(): {};
42
+ };
43
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,wBAAgB,UAAU;;;;;;;;;;sBAcJ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC;;YAGtE,iDAAiD;;YAEjD,mEAAmE;kCAC7C;gBAAE,SAAS,EAAE,MAAM,CAAC;gBAAC,GAAG,EAAE,UAAU,CAAC;gBAAC,SAAS,EAAE,MAAM,CAAA;aAAE;;;;EAiBxF"}
package/dist/client.js ADDED
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Client plugin for @dbsc-toolkit/better-auth.
3
+ *
4
+ * Provides TypeScript inference for the DBSC endpoints so your
5
+ * Better Auth client knows about /dbsc/* and /dbsc-bound/* paths.
6
+ *
7
+ * Usage:
8
+ * import { createAuthClient } from "better-auth/client"
9
+ * import { dbscClient } from "@dbsc-toolkit/better-auth/client"
10
+ *
11
+ * export const authClient = createAuthClient({
12
+ * plugins: [dbscClient()]
13
+ * })
14
+ *
15
+ * Then initialize the polyfill in your browser entry point:
16
+ * import { initBoundDbsc } from "dbsc-toolkit/client"
17
+ * initBoundDbsc({ baseUrl: "" })
18
+ */
19
+ export function dbscClient() {
20
+ return {
21
+ id: "dbsc-toolkit",
22
+ // Path → HTTP method map so Better Auth's client can infer the right fetch
23
+ pathMethods: {
24
+ "/dbsc/registration": "POST",
25
+ "/dbsc/refresh": "POST",
26
+ "/dbsc-bound/state": "GET",
27
+ "/dbsc-bound/challenge": "GET",
28
+ "/dbsc-bound/registration": "POST",
29
+ "/dbsc-bound/refresh": "POST",
30
+ },
31
+ getActions(fetch) {
32
+ return {
33
+ dbsc: {
34
+ /** Check bound state for the current session. */
35
+ getBoundState: () => fetch("/dbsc-bound/state"),
36
+ /** Manually trigger polyfill registration (normally automatic). */
37
+ registerBound: (body) => fetch("/dbsc-bound/registration", {
38
+ method: "POST",
39
+ headers: { "content-type": "application/json" },
40
+ body: JSON.stringify(body),
41
+ }),
42
+ },
43
+ };
44
+ },
45
+ getAtoms() {
46
+ // No reactive state atoms needed for DBSC — the binding happens
47
+ // transparently in the background. Add nanostores here if you need
48
+ // UI that reflects binding status.
49
+ return {};
50
+ },
51
+ };
52
+ }
53
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,UAAU,UAAU;IACxB,OAAO;QACL,EAAE,EAAE,cAAc;QAElB,2EAA2E;QAC3E,WAAW,EAAE;YACX,oBAAoB,EAAE,MAAM;YAC5B,eAAe,EAAE,MAAM;YACvB,mBAAmB,EAAE,KAAK;YAC1B,uBAAuB,EAAE,KAAK;YAC9B,0BAA0B,EAAE,MAAM;YAClC,qBAAqB,EAAE,MAAM;SACrB;QAEV,UAAU,CAAC,KAAiE;YAC1E,OAAO;gBACL,IAAI,EAAE;oBACJ,iDAAiD;oBACjD,aAAa,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,mBAAmB,CAAC;oBAC/C,mEAAmE;oBACnE,aAAa,EAAE,CAAC,IAA+D,EAAE,EAAE,CACjF,KAAK,CAAC,0BAA0B,EAAE;wBAChC,MAAM,EAAE,MAAM;wBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;wBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;qBAC3B,CAAC;iBACL;aACF,CAAC;QACJ,CAAC;QAED,QAAQ;YACN,gEAAgE;YAChE,mEAAmE;YACnE,mCAAmC;YACnC,OAAO,EAAE,CAAC;QACZ,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Express adapter for @dbsc-toolkit/better-auth.
3
+ *
4
+ * One factory call gives you the same `install / requireProof` shape the
5
+ * Express adapter in `dbsc-toolkit` exposes, but backed by Better Auth's DB.
6
+ *
7
+ * import { dbscExpress } from "@dbsc-toolkit/better-auth/express"
8
+ * const dbsc = dbscExpress(auth)
9
+ * dbsc.install(app)
10
+ * app.get("/profile", dbsc.requireProof(), handler)
11
+ *
12
+ * The storage adapter is resolved lazily from `auth.$context` on the first
13
+ * DBSC request — that's why `dbscExpress()` is sync and never touches the DB
14
+ * at module-evaluation time.
15
+ */
16
+ import type { Express, RequestHandler } from "express";
17
+ import { type AnyTelemetryEvent, type ProofReplayCache, type RateLimiter } from "dbsc-toolkit";
18
+ export interface AuthLike {
19
+ $context: Promise<{
20
+ adapter: any;
21
+ internalAdapter: any;
22
+ }>;
23
+ }
24
+ export interface DbscExpressOptions {
25
+ /** Base path Better Auth is mounted at. Default "/api/auth". Must match `dbsc({ basePath })` in your auth.ts. */
26
+ basePath?: string;
27
+ /** Mount path for the polyfill SDK + init shim. Default "/dbsc-client". Set false to skip serving. */
28
+ clientPath?: string | false;
29
+ /** Cookie scope. Default "host". */
30
+ cookieScope?: "host" | "site";
31
+ /** Required when cookieScope is "site". */
32
+ cookieDomain?: string;
33
+ /** Use `Secure` cookies + `__Host-`/`__Secure-` prefixes. Default true. Set false on bare-http localhost. */
34
+ secure?: boolean;
35
+ /** Bound cookie TTL (ms). Default 600_000 (10 min). */
36
+ sessionTtl?: number;
37
+ /** Replay cache for per-request proofs. Default no-op. */
38
+ replayCache?: ProofReplayCache;
39
+ /** Rate limiter for /dbsc/* routes. Default no-op. */
40
+ rateLimiter?: RateLimiter;
41
+ /** Telemetry hook fired on registration, refresh, failures. */
42
+ onEvent?: (event: AnyTelemetryEvent) => void | Promise<void>;
43
+ }
44
+ export interface DbscExpressKit {
45
+ /** Mount the full DBSC surface: protocol routes + polyfill routes + /dbsc-client/*. */
46
+ install(app: Express): Express;
47
+ /** Raw middleware for manual mounting (skips install()'s static SDK + init shim). */
48
+ middleware(): RequestHandler;
49
+ /** Route guard that verifies the X-Dbsc-Bound-Proof header. 403 on missing/invalid. */
50
+ requireProof(): RequestHandler;
51
+ }
52
+ /**
53
+ * Build a DBSC kit for an Express + Better Auth app.
54
+ *
55
+ * The Better Auth plugin (`dbsc()` in `auth.ts`) issues the
56
+ * `Secure-Session-Registration` header after every sign-in. This kit handles
57
+ * everything that follows: the protocol routes Chrome posts to, the polyfill
58
+ * endpoints, and the per-request proof verifier.
59
+ *
60
+ * const dbsc = dbscExpress(auth)
61
+ * dbsc.install(app)
62
+ * app.get("/profile", dbsc.requireProof(), profileHandler)
63
+ */
64
+ export declare function dbscExpress(auth: AuthLike, opts?: DbscExpressOptions): DbscExpressKit;
65
+ //# sourceMappingURL=express.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"express.d.ts","sourceRoot":"","sources":["../src/express.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAmC,MAAM,SAAS,CAAC;AAExF,OAAO,EAML,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,WAAW,EACjB,MAAM,cAAc,CAAC;AAKtB,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,OAAO,CAAC;QAChB,OAAO,EAAE,GAAG,CAAC;QACb,eAAe,EAAE,GAAG,CAAC;KACtB,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,kBAAkB;IACjC,iHAAiH;IACjH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sGAAsG;IACtG,UAAU,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAC5B,oCAAoC;IACpC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,2CAA2C;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,6GAA6G;IAC7G,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,uDAAuD;IACvD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,WAAW,CAAC,EAAE,gBAAgB,CAAC;IAC/B,sDAAsD;IACtD,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,+DAA+D;IAC/D,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9D;AAuDD,MAAM,WAAW,cAAc;IAC7B,uFAAuF;IACvF,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC;IAC/B,qFAAqF;IACrF,UAAU,IAAI,cAAc,CAAC;IAC7B,uFAAuF;IACvF,YAAY,IAAI,cAAc,CAAC;CAChC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,GAAE,kBAAuB,GAAG,cAAc,CA6DzF"}
@@ -0,0 +1,124 @@
1
+ import { createDbsc } from "dbsc-toolkit/express";
2
+ import { createBetterAuthStorageAdapter } from "./adapter.js";
3
+ import { buildInitScript } from "./init-script.js";
4
+ const DEFAULT_BASE_PATH = "/api/auth";
5
+ const DEFAULT_CLIENT_PATH = "/dbsc-client";
6
+ /**
7
+ * Wraps a `Promise<StorageAdapter>` as a synchronous `StorageAdapter` whose
8
+ * methods await the underlying adapter on first call. Lets us hand a
9
+ * StorageAdapter to `createDbsc()` synchronously, without ever resolving
10
+ * `auth.$context` at module load.
11
+ */
12
+ function lazyStorage(resolve) {
13
+ let cached;
14
+ const get = async () => {
15
+ if (!cached)
16
+ cached = await resolve();
17
+ return cached;
18
+ };
19
+ return {
20
+ async getSession(id) {
21
+ return (await get()).getSession(id);
22
+ },
23
+ async setSession(session) {
24
+ return (await get()).setSession(session);
25
+ },
26
+ async deleteSession(id) {
27
+ return (await get()).deleteSession(id);
28
+ },
29
+ async getBoundKey(sessionId, kind) {
30
+ return (await get()).getBoundKey(sessionId, kind);
31
+ },
32
+ async setBoundKey(key) {
33
+ return (await get()).setBoundKey(key);
34
+ },
35
+ async deleteBoundKey(sessionId, kind) {
36
+ return (await get()).deleteBoundKey(sessionId, kind);
37
+ },
38
+ async getChallenge(jti) {
39
+ return (await get()).getChallenge(jti);
40
+ },
41
+ async setChallenge(challenge) {
42
+ return (await get()).setChallenge(challenge);
43
+ },
44
+ async consumeChallenge(jti) {
45
+ return (await get()).consumeChallenge(jti);
46
+ },
47
+ async revokeSession(sessionId) {
48
+ return (await get()).revokeSession(sessionId);
49
+ },
50
+ async revokeAllForUser(userId) {
51
+ return (await get()).revokeAllForUser(userId);
52
+ },
53
+ };
54
+ }
55
+ /**
56
+ * Build a DBSC kit for an Express + Better Auth app.
57
+ *
58
+ * The Better Auth plugin (`dbsc()` in `auth.ts`) issues the
59
+ * `Secure-Session-Registration` header after every sign-in. This kit handles
60
+ * everything that follows: the protocol routes Chrome posts to, the polyfill
61
+ * endpoints, and the per-request proof verifier.
62
+ *
63
+ * const dbsc = dbscExpress(auth)
64
+ * dbsc.install(app)
65
+ * app.get("/profile", dbsc.requireProof(), profileHandler)
66
+ */
67
+ export function dbscExpress(auth, opts = {}) {
68
+ const basePath = opts.basePath ?? DEFAULT_BASE_PATH;
69
+ const clientPath = opts.clientPath ?? DEFAULT_CLIENT_PATH;
70
+ const secure = opts.secure ?? true;
71
+ const storage = lazyStorage(async () => {
72
+ const ctx = await auth.$context;
73
+ return createBetterAuthStorageAdapter(ctx.adapter, ctx.internalAdapter);
74
+ });
75
+ // Mount paths reflect basePath so Chrome's auto-POST lands correctly.
76
+ const registrationPath = `${basePath}/dbsc/registration`;
77
+ const refreshPath = `${basePath}/dbsc/refresh`;
78
+ const boundStatePath = `${basePath}/dbsc-bound/state`;
79
+ const boundChallengePath = `${basePath}/dbsc-bound/challenge`;
80
+ const boundRegistrationPath = `${basePath}/dbsc-bound/registration`;
81
+ const boundRefreshPath = `${basePath}/dbsc-bound/refresh`;
82
+ const kit = createDbsc({
83
+ storage,
84
+ secure,
85
+ registrationPath,
86
+ refreshPath,
87
+ boundStatePath,
88
+ boundChallengePath,
89
+ boundRegistrationPath,
90
+ boundRefreshPath,
91
+ clientPath: clientPath === false ? false : clientPath,
92
+ ...(opts.cookieScope !== undefined && { cookieScope: opts.cookieScope }),
93
+ ...(opts.cookieDomain !== undefined && { cookieDomain: opts.cookieDomain }),
94
+ ...(opts.sessionTtl !== undefined && { sessionTtl: opts.sessionTtl }),
95
+ ...(opts.replayCache !== undefined && { replayCache: opts.replayCache }),
96
+ ...(opts.rateLimiter !== undefined && { rateLimiter: opts.rateLimiter }),
97
+ ...(opts.onEvent !== undefined && { onEvent: opts.onEvent }),
98
+ });
99
+ function install(app) {
100
+ // Serve /dbsc-client/init.js BEFORE the static directory below so it wins
101
+ // the match. The shim re-points the polyfill SDK at the basePath the
102
+ // user actually configured.
103
+ if (clientPath !== false) {
104
+ const initJs = buildInitScript({ basePath, clientPath });
105
+ const initRoute = `${clientPath}/init.js`;
106
+ app.get(initRoute, (_req, res) => {
107
+ res.setHeader("Content-Type", "application/javascript; charset=utf-8");
108
+ res.setHeader("Cache-Control", "public, max-age=300");
109
+ res.send(initJs);
110
+ });
111
+ }
112
+ // kit.install mounts the dbsc-toolkit middleware (all protocol + bound
113
+ // routes) and serves the polyfill SDK static files at clientPath.
114
+ return kit.install(app);
115
+ }
116
+ return {
117
+ install,
118
+ middleware: kit.middleware,
119
+ requireProof() {
120
+ return kit.requireProof();
121
+ },
122
+ };
123
+ }
124
+ //# sourceMappingURL=express.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"express.js","sourceRoot":"","sources":["../src/express.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * @dbsc-toolkit/better-auth
3
+ *
4
+ * DBSC (Device Bound Session Credentials) plugin for Better Auth.
5
+ * Powered by dbsc-toolkit — hardware-bound sessions on Chromium 145+,
6
+ * Web Crypto polyfill for Firefox/Safari/older Chromium.
7
+ *
8
+ * Usage:
9
+ * import { betterAuth } from "better-auth"
10
+ * import { dbsc } from "@dbsc-toolkit/better-auth"
11
+ *
12
+ * export const auth = betterAuth({
13
+ * plugins: [dbsc()]
14
+ * })
15
+ */
16
+ import { type AnyTelemetryEvent } from "dbsc-toolkit";
17
+ export interface DbscPluginOptions {
18
+ /**
19
+ * The base path where Better Auth is mounted. Default: "/api/auth".
20
+ * Used to build the full registration path in the Secure-Session-Registration header.
21
+ */
22
+ basePath?: string;
23
+ /** Cookie scope: "host" (default, __Host-) or "site" (__Secure- + Domain). */
24
+ cookieScope?: "host" | "site";
25
+ /** Required when cookieScope is "site". E.g. "example.com" */
26
+ cookieDomain?: string;
27
+ /** Bound cookie TTL in ms. Default: 600_000 (10 min) */
28
+ sessionTtl?: number;
29
+ /** Telemetry hook */
30
+ onEvent?: (event: AnyTelemetryEvent) => void | Promise<void>;
31
+ }
32
+ export declare function dbsc(opts?: DbscPluginOptions): object;
33
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAOL,KAAK,iBAAiB,EACvB,MAAM,cAAc,CAAC;AAKtB,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,8DAA8D;IAC9D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,wDAAwD;IACxD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qBAAqB;IACrB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9D;AAMD,wBAAgB,IAAI,CAAC,IAAI,GAAE,iBAAsB,GAAG,MAAM,CA2IzD"}
package/dist/index.js ADDED
@@ -0,0 +1,138 @@
1
+ /**
2
+ * @dbsc-toolkit/better-auth
3
+ *
4
+ * DBSC (Device Bound Session Credentials) plugin for Better Auth.
5
+ * Powered by dbsc-toolkit — hardware-bound sessions on Chromium 145+,
6
+ * Web Crypto polyfill for Firefox/Safari/older Chromium.
7
+ *
8
+ * Usage:
9
+ * import { betterAuth } from "better-auth"
10
+ * import { dbsc } from "@dbsc-toolkit/better-auth"
11
+ *
12
+ * export const auth = betterAuth({
13
+ * plugins: [dbsc()]
14
+ * })
15
+ */
16
+ import { issueChallenge, buildRegistrationHeader, REGISTRATION_HEADER, LEGACY_REGISTRATION_HEADER, resolveCookieNames, } from "dbsc-toolkit";
17
+ import { createBetterAuthStorageAdapter } from "./adapter.js";
18
+ import { dbscSchema } from "./schema.js";
19
+ const REGISTRATION_PATH = "/dbsc/registration";
20
+ const DEFAULT_SESSION_TTL = 600_000;
21
+ const DEFAULT_BASE_PATH = "/api/auth";
22
+ export function dbsc(opts = {}) {
23
+ const { basePath = DEFAULT_BASE_PATH, cookieScope = "host", cookieDomain, sessionTtl = DEFAULT_SESSION_TTL, } = opts;
24
+ const secure = true;
25
+ const scopeOpts = cookieDomain
26
+ ? { secure, cookieScope, cookieDomain }
27
+ : { secure, cookieScope };
28
+ const names = resolveCookieNames(scopeOpts);
29
+ function regCookieHeader(sessionId) {
30
+ return [
31
+ `${names.reg}=${sessionId}`,
32
+ "HttpOnly",
33
+ "Path=/",
34
+ "SameSite=Lax",
35
+ `Max-Age=${Math.floor(sessionTtl / 1000)}`,
36
+ ...(secure ? ["Secure"] : []),
37
+ ...(cookieDomain ? [`Domain=${cookieDomain}`] : []),
38
+ ].join("; ");
39
+ }
40
+ function sessionCookieHeader(sessionId) {
41
+ return [
42
+ `${names.bound}=${sessionId}`,
43
+ "HttpOnly",
44
+ "Path=/",
45
+ "SameSite=Lax",
46
+ `Max-Age=${Math.floor(sessionTtl / 1000)}`,
47
+ ...(secure ? ["Secure"] : []),
48
+ ...(cookieDomain ? [`Domain=${cookieDomain}`] : []),
49
+ ].join("; ");
50
+ }
51
+ function challengeCookieHeader(jti) {
52
+ return [
53
+ `${names.challenge}=${jti}`,
54
+ "HttpOnly",
55
+ "Path=/",
56
+ "SameSite=Lax",
57
+ `Max-Age=300`,
58
+ ...(secure ? ["Secure"] : []),
59
+ ...(cookieDomain ? [`Domain=${cookieDomain}`] : []),
60
+ ].join("; ");
61
+ }
62
+ return {
63
+ id: "dbsc-toolkit",
64
+ schema: dbscSchema,
65
+ // The DBSC protocol routes do NOT live inside the plugin — Better Auth's
66
+ // createAuthEndpoint refuses POSTs without a body (responds 415), and
67
+ // Chrome's registration request has the JWS in a header with no body.
68
+ // Use mountDbscRoutes(app, auth) on your Hono/Express app instead.
69
+ hooks: {
70
+ after: [
71
+ {
72
+ // Fires after any endpoint whose response contains a token — sign-in,
73
+ // sign-up, OAuth callback, magic link, passkey. Better Auth returns
74
+ // { token, user } for all these paths.
75
+ matcher: (ctx) => {
76
+ const returned = ctx.context?.returned;
77
+ const token = returned?.["token"];
78
+ return typeof token === "string" && token.length > 0;
79
+ },
80
+ handler: async (ctx) => {
81
+ const empty = { headers: new Headers() };
82
+ const returned = ctx.context?.returned;
83
+ const token = returned?.token;
84
+ if (!token)
85
+ return empty;
86
+ const internalAdapter = ctx.context?.internalAdapter;
87
+ if (!internalAdapter?.findSession)
88
+ return empty;
89
+ let sessionId;
90
+ let userId;
91
+ try {
92
+ const result = await internalAdapter.findSession(token);
93
+ sessionId = result?.session?.id;
94
+ userId = result?.session?.userId ?? result?.user?.id;
95
+ }
96
+ catch {
97
+ return empty;
98
+ }
99
+ if (!sessionId || !userId)
100
+ return empty;
101
+ const store = createBetterAuthStorageAdapter(ctx.context.adapter, ctx.context.internalAdapter);
102
+ const now = Date.now();
103
+ const existing = await store.getSession(sessionId);
104
+ if (!existing) {
105
+ await store.setSession({
106
+ id: sessionId,
107
+ userId,
108
+ tier: "none",
109
+ createdAt: now,
110
+ expiresAt: now + sessionTtl,
111
+ lastRefreshAt: now,
112
+ });
113
+ }
114
+ const { jti } = await issueChallenge(sessionId, store, sessionTtl);
115
+ const regHeader = buildRegistrationHeader({
116
+ registrationPath: `${basePath}${REGISTRATION_PATH}`,
117
+ challenge: jti,
118
+ cookieName: names.bound,
119
+ });
120
+ // Return headers — Better Auth merges these into the response.
121
+ // Three cookies:
122
+ // - __Host-dbsc-session: bound cookie Chrome watches
123
+ // - __Host-dbsc-reg: carries sessionId to /dbsc/registration
124
+ // - __Host-dbsc-challenge: carries jti to /dbsc/registration
125
+ const headers = new Headers();
126
+ headers.set(REGISTRATION_HEADER, regHeader);
127
+ headers.set(LEGACY_REGISTRATION_HEADER, regHeader);
128
+ headers.append("Set-Cookie", sessionCookieHeader(sessionId));
129
+ headers.append("Set-Cookie", regCookieHeader(sessionId));
130
+ headers.append("Set-Cookie", challengeCookieHeader(jti));
131
+ return { headers };
132
+ },
133
+ },
134
+ ],
135
+ },
136
+ };
137
+ }
138
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Generates the browser-side init shim served at `<clientPath>/init.js`.
3
+ *
4
+ * The user drops one tag in their HTML:
5
+ *
6
+ * <script src="/dbsc-client/init.js"></script>
7
+ *
8
+ * The shim imports the polyfill SDK from `<clientPath>/index.js`, calls
9
+ * `initBoundDbsc()` with paths that match the configured Better Auth
10
+ * basePath, and exposes `window.boundFetch` so app code can sign per-request
11
+ * proofs by calling `boundFetch(...)` instead of `fetch(...)`.
12
+ */
13
+ export interface InitScriptOptions {
14
+ basePath: string;
15
+ clientPath: string;
16
+ }
17
+ export declare function buildInitScript(opts: InitScriptOptions): string;
18
+ //# sourceMappingURL=init-script.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-script.d.ts","sourceRoot":"","sources":["../src/init-script.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CAiC/D"}
@@ -0,0 +1,35 @@
1
+ export function buildInitScript(opts) {
2
+ const { basePath, clientPath } = opts;
3
+ return `// @dbsc-toolkit/better-auth — browser init shim
4
+ import { initBoundDbsc, wrapFetch, clearBoundKey } from "${clientPath}/index.js";
5
+
6
+ const paths = {
7
+ statePath: "${basePath}/dbsc-bound/state",
8
+ challengePath: "${basePath}/dbsc-bound/challenge",
9
+ registrationPath: "${basePath}/dbsc-bound/registration",
10
+ refreshPath: "${basePath}/dbsc-bound/refresh",
11
+ };
12
+
13
+ // Polyfill kicks in on Firefox / Safari / older Chromium. On Chromium 145+
14
+ // native DBSC runs first; the polyfill co-registers a key so per-request
15
+ // proofs work everywhere.
16
+ //
17
+ // Expose initDbsc() on window so callers can re-trigger the flow after a
18
+ // fresh sign-in or sign-up — without that, a logged-out page-load probe
19
+ // resolves to "unbound" and the key record never appears.
20
+ window.initDbsc = () => initBoundDbsc({ nativeProbeWindowMs: 8000, ...paths });
21
+
22
+ // boundFetch signs every request body (empty bytes for GET). Replace
23
+ // \`fetch\` with \`boundFetch\` on any call to a requireProof()-guarded route.
24
+ window.boundFetch = wrapFetch({ signBody: true });
25
+ window.clearBoundKey = clearBoundKey;
26
+
27
+ // First probe on page load — finds an existing binding (returning user) or
28
+ // resolves to unbound (logged-out user). Either way, callers must call
29
+ // window.initDbsc() again after sign-up / sign-in so the SDK observes the
30
+ // newly issued session.
31
+ window.__dbscOutcome = window.initDbsc();
32
+ window.__dbscOutcome.then((o) => console.log("[dbsc]", o)).catch((e) => console.error("[dbsc]", e));
33
+ `;
34
+ }
35
+ //# sourceMappingURL=init-script.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-script.js","sourceRoot":"","sources":["../src/init-script.ts"],"names":[],"mappings":"AAiBA,MAAM,UAAU,eAAe,CAAC,IAAuB;IACrD,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC;IACtC,OAAO;2DACkD,UAAU;;;gBAGrD,QAAQ;oBACJ,QAAQ;uBACL,QAAQ;kBACb,QAAQ;;;;;;;;;;;;;;;;;;;;;;;CAuBzB,CAAC;AACF,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Internal helpers — exposed for advanced users who need to construct the
3
+ * storage adapter manually (e.g. for custom requireProof middleware in their
4
+ * own routes). Normal usage does NOT need this import.
5
+ */
6
+ export { createBetterAuthStorageAdapter } from "./adapter.js";
7
+ export type { BetterAuthDbAdapter, BetterAuthInternalAdapter } from "./adapter.js";
8
+ //# sourceMappingURL=internal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,8BAA8B,EAAE,MAAM,cAAc,CAAC;AAC9D,YAAY,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Internal helpers — exposed for advanced users who need to construct the
3
+ * storage adapter manually (e.g. for custom requireProof middleware in their
4
+ * own routes). Normal usage does NOT need this import.
5
+ */
6
+ export { createBetterAuthStorageAdapter } from "./adapter.js";
7
+ //# sourceMappingURL=internal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal.js","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,8BAA8B,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Better Auth schema extension for dbsc-toolkit.
3
+ *
4
+ * Defines two tables:
5
+ * dbscSession — tracks binding state (tier, lastRefreshAt) per session
6
+ * dbscBoundKey — stores the JWK for native (TPM) and bound (polyfill) keys
7
+ *
8
+ * Challenges are stored in Better Auth's built-in `verification` table
9
+ * so we get atomic consumeVerificationValue for free.
10
+ */
11
+ export declare const dbscSchema: {
12
+ readonly dbscSession: {
13
+ readonly fields: {
14
+ readonly userId: {
15
+ readonly type: "string";
16
+ readonly required: true;
17
+ readonly references: {
18
+ readonly model: "user";
19
+ readonly field: "id";
20
+ };
21
+ };
22
+ readonly tier: {
23
+ readonly type: "string";
24
+ readonly required: true;
25
+ };
26
+ readonly createdAt: {
27
+ readonly type: "number";
28
+ readonly required: true;
29
+ };
30
+ readonly expiresAt: {
31
+ readonly type: "number";
32
+ readonly required: true;
33
+ };
34
+ readonly lastRefreshAt: {
35
+ readonly type: "number";
36
+ readonly required: true;
37
+ };
38
+ };
39
+ };
40
+ readonly dbscBoundKey: {
41
+ readonly fields: {
42
+ readonly sessionId: {
43
+ readonly type: "string";
44
+ readonly required: true;
45
+ readonly references: {
46
+ readonly model: "dbscSession";
47
+ readonly field: "id";
48
+ };
49
+ };
50
+ readonly kind: {
51
+ readonly type: "string";
52
+ readonly required: true;
53
+ };
54
+ readonly jwk: {
55
+ readonly type: "string";
56
+ readonly required: true;
57
+ };
58
+ readonly createdAt: {
59
+ readonly type: "number";
60
+ readonly required: true;
61
+ };
62
+ readonly algorithm: {
63
+ readonly type: "string";
64
+ readonly required: true;
65
+ };
66
+ };
67
+ };
68
+ };
69
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuDb,CAAC"}