dbsc-toolkit 2.8.1 → 2.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/core/cookies/options.d.ts +56 -0
- package/dist/core/cookies/options.d.ts.map +1 -0
- package/dist/core/cookies/options.js +84 -0
- package/dist/core/cookies/options.js.map +1 -0
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/types.d.ts +15 -5
- package/dist/core/types.d.ts.map +1 -1
- package/dist/express/create-dbsc.d.ts.map +1 -1
- package/dist/express/create-dbsc.js +19 -7
- package/dist/express/create-dbsc.js.map +1 -1
- package/dist/express/index.d.ts +5 -1
- package/dist/express/index.d.ts.map +1 -1
- package/dist/express/index.js +40 -25
- package/dist/express/index.js.map +1 -1
- package/dist/fastify/create-dbsc.d.ts.map +1 -1
- package/dist/fastify/create-dbsc.js +17 -6
- package/dist/fastify/create-dbsc.js.map +1 -1
- package/dist/fastify/index.d.ts +5 -1
- package/dist/fastify/index.d.ts.map +1 -1
- package/dist/fastify/index.js +24 -11
- package/dist/fastify/index.js.map +1 -1
- package/dist/hono/create-dbsc.d.ts.map +1 -1
- package/dist/hono/create-dbsc.js +17 -6
- package/dist/hono/create-dbsc.js.map +1 -1
- package/dist/hono/index.d.ts +5 -1
- package/dist/hono/index.d.ts.map +1 -1
- package/dist/hono/index.js +30 -12
- package/dist/hono/index.js.map +1 -1
- package/dist/nextjs/create-dbsc.d.ts.map +1 -1
- package/dist/nextjs/create-dbsc.js +15 -2
- package/dist/nextjs/create-dbsc.js.map +1 -1
- package/dist/nextjs/index.d.ts +7 -1
- package/dist/nextjs/index.d.ts.map +1 -1
- package/dist/nextjs/index.js +41 -23
- package/dist/nextjs/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -129,6 +129,8 @@ app.post("/logout", async (req, res) => {
|
|
|
129
129
|
|
|
130
130
|
**No server-side session id** (NextAuth JWT mode, iron-session, Lucia stateless)? Call `dbsc.bind(res, { userId })` with no id — the kit derives a stable one and manages a per-device cookie so each browser of the same user binds independently. Per-system recipes: [docs/integration-recipes.md](./docs/integration-recipes.md).
|
|
131
131
|
|
|
132
|
+
**App split across subdomains** (`app.example.com` + `api.example.com`)? Default `__Host-` cookies are origin-locked — keep DBSC on one origin (proxy `/dbsc/*` and `/dbsc-bound/*` through the UI host) for the strongest setting. If a same-origin layout is genuinely not workable, v2.9.0+ exposes `cookieScope: "site"` + `cookieDomain: "example.com"` on `createDbsc({...})`, switching the binding cookies to `__Secure-` with a `Domain` attribute. The validator throws at construction if either is wrong, so misconfiguration is loud, not silent. Trade-off and concrete recipe: [docs/integration-recipes.md#multi-subdomain-apps-cookiescope-site](./docs/integration-recipes.md#multi-subdomain-apps-cookiescope-site).
|
|
133
|
+
|
|
132
134
|
**The full step-by-step** — every option and its default, the `autoBind` transparent-rollout variant, the per-route policy table, the migration timeline — is in [docs/integrating-existing-auth.md](./docs/integrating-existing-auth.md).
|
|
133
135
|
|
|
134
136
|
## Protect your routes
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cookie-scope helpers shared by every adapter (v2.9+).
|
|
3
|
+
*
|
|
4
|
+
* Single source of truth for the cookie prefix (`__Host-` vs `__Secure-`),
|
|
5
|
+
* the `Domain` attribute, and the `attributes` string echoed back in the
|
|
6
|
+
* registration response's `credentials[].attributes` field.
|
|
7
|
+
*
|
|
8
|
+
* The four adapters wrap framework-specific cookie APIs around the values
|
|
9
|
+
* returned here. The validator throws on construction so a missing
|
|
10
|
+
* `cookieDomain` cannot silently degrade into a broken state at request
|
|
11
|
+
* time.
|
|
12
|
+
*/
|
|
13
|
+
export type CookieScope = "host" | "site";
|
|
14
|
+
export interface CookieScopeOptions {
|
|
15
|
+
secure: boolean;
|
|
16
|
+
cookieScope?: CookieScope;
|
|
17
|
+
cookieDomain?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface CookieScopeResolved {
|
|
20
|
+
/** Whether the cookies use the `__Host-` prefix (host scope, secure). */
|
|
21
|
+
hostPrefix: boolean;
|
|
22
|
+
/** `"__Host-"`, `"__Secure-"`, or `""` (insecure dev). */
|
|
23
|
+
prefix: "__Host-" | "__Secure-" | "";
|
|
24
|
+
/** The `Domain` attribute value, or undefined when no domain is emitted. */
|
|
25
|
+
domain: string | undefined;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Validates a cookie-scope configuration and returns the resolved values
|
|
29
|
+
* the adapters consume. Throws when `"site"` scope is requested without a
|
|
30
|
+
* `cookieDomain`, or when an insecure config tries to use site scope (a
|
|
31
|
+
* `__Secure-` cookie requires the `Secure` flag, which requires HTTPS).
|
|
32
|
+
*/
|
|
33
|
+
export declare function resolveCookieScope(opts: CookieScopeOptions): CookieScopeResolved;
|
|
34
|
+
/**
|
|
35
|
+
* Returns the three cookie names (`bound`, `reg`, `challenge`) the adapters
|
|
36
|
+
* read and write. Encapsulates the prefix swap so callers never concatenate
|
|
37
|
+
* a prefix by hand.
|
|
38
|
+
*/
|
|
39
|
+
export declare function cookieNames(opts: CookieScopeOptions): {
|
|
40
|
+
bound: string;
|
|
41
|
+
reg: string;
|
|
42
|
+
challenge: string;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* The name of the per-device cookie used by the JWT-mode `bind()` path.
|
|
46
|
+
* Same prefix rules as the binding cookies above.
|
|
47
|
+
*/
|
|
48
|
+
export declare function deviceCookieName(opts: CookieScopeOptions): string;
|
|
49
|
+
/**
|
|
50
|
+
* Returns the `attributes` string echoed back in the registration response's
|
|
51
|
+
* `credentials[].attributes` field, which Chromium re-reads to know how to
|
|
52
|
+
* re-issue the bound cookie on refresh. Must match what the server actually
|
|
53
|
+
* sets in `Set-Cookie`, byte for byte, or Chromium drops the binding.
|
|
54
|
+
*/
|
|
55
|
+
export declare function cookieAttributesString(opts: CookieScopeOptions): string;
|
|
56
|
+
//# sourceMappingURL=options.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../../src/core/cookies/options.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,CAAC;AAE1C,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB;IAClC,yEAAyE;IACzE,UAAU,EAAE,OAAO,CAAC;IACpB,0DAA0D;IAC1D,MAAM,EAAE,SAAS,GAAG,WAAW,GAAG,EAAE,CAAC;IACrC,4EAA4E;IAC5E,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,kBAAkB,GAAG,mBAAmB,CAwChF;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,kBAAkB,GAAG;IACrD,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;CACnB,CAOA;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAGjE;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAKvE"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cookie-scope helpers shared by every adapter (v2.9+).
|
|
3
|
+
*
|
|
4
|
+
* Single source of truth for the cookie prefix (`__Host-` vs `__Secure-`),
|
|
5
|
+
* the `Domain` attribute, and the `attributes` string echoed back in the
|
|
6
|
+
* registration response's `credentials[].attributes` field.
|
|
7
|
+
*
|
|
8
|
+
* The four adapters wrap framework-specific cookie APIs around the values
|
|
9
|
+
* returned here. The validator throws on construction so a missing
|
|
10
|
+
* `cookieDomain` cannot silently degrade into a broken state at request
|
|
11
|
+
* time.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Validates a cookie-scope configuration and returns the resolved values
|
|
15
|
+
* the adapters consume. Throws when `"site"` scope is requested without a
|
|
16
|
+
* `cookieDomain`, or when an insecure config tries to use site scope (a
|
|
17
|
+
* `__Secure-` cookie requires the `Secure` flag, which requires HTTPS).
|
|
18
|
+
*/
|
|
19
|
+
export function resolveCookieScope(opts) {
|
|
20
|
+
const scope = opts.cookieScope ?? "host";
|
|
21
|
+
const secure = opts.secure;
|
|
22
|
+
if (scope === "site") {
|
|
23
|
+
if (!opts.cookieDomain) {
|
|
24
|
+
throw new Error('dbsc: cookieScope: "site" requires cookieDomain. ' +
|
|
25
|
+
"Set cookieDomain to the registrable apex (e.g. \"example.com\") " +
|
|
26
|
+
"so the binding cookie can be shared across subdomains. " +
|
|
27
|
+
'Drop cookieScope to keep the default "host" mode.');
|
|
28
|
+
}
|
|
29
|
+
if (!secure) {
|
|
30
|
+
throw new Error('dbsc: cookieScope: "site" requires secure: true. ' +
|
|
31
|
+
"The __Secure- prefix is rejected by browsers without the Secure flag.");
|
|
32
|
+
}
|
|
33
|
+
if (opts.cookieDomain.startsWith(".")) {
|
|
34
|
+
throw new Error('dbsc: cookieDomain must not start with a leading dot. ' +
|
|
35
|
+
'Use "example.com", not ".example.com".');
|
|
36
|
+
}
|
|
37
|
+
return { hostPrefix: false, prefix: "__Secure-", domain: opts.cookieDomain };
|
|
38
|
+
}
|
|
39
|
+
// host scope
|
|
40
|
+
if (opts.cookieDomain) {
|
|
41
|
+
throw new Error('dbsc: cookieDomain is only valid when cookieScope: "site". ' +
|
|
42
|
+
'Remove cookieDomain or set cookieScope: "site".');
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
hostPrefix: secure,
|
|
46
|
+
prefix: secure ? "__Host-" : "",
|
|
47
|
+
domain: undefined,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Returns the three cookie names (`bound`, `reg`, `challenge`) the adapters
|
|
52
|
+
* read and write. Encapsulates the prefix swap so callers never concatenate
|
|
53
|
+
* a prefix by hand.
|
|
54
|
+
*/
|
|
55
|
+
export function cookieNames(opts) {
|
|
56
|
+
const { prefix } = resolveCookieScope(opts);
|
|
57
|
+
return {
|
|
58
|
+
bound: `${prefix}dbsc-session`,
|
|
59
|
+
reg: `${prefix}dbsc-reg`,
|
|
60
|
+
challenge: `${prefix}dbsc-challenge`,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* The name of the per-device cookie used by the JWT-mode `bind()` path.
|
|
65
|
+
* Same prefix rules as the binding cookies above.
|
|
66
|
+
*/
|
|
67
|
+
export function deviceCookieName(opts) {
|
|
68
|
+
const { prefix } = resolveCookieScope(opts);
|
|
69
|
+
return `${prefix}dbsc-device`;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Returns the `attributes` string echoed back in the registration response's
|
|
73
|
+
* `credentials[].attributes` field, which Chromium re-reads to know how to
|
|
74
|
+
* re-issue the bound cookie on refresh. Must match what the server actually
|
|
75
|
+
* sets in `Set-Cookie`, byte for byte, or Chromium drops the binding.
|
|
76
|
+
*/
|
|
77
|
+
export function cookieAttributesString(opts) {
|
|
78
|
+
const { domain } = resolveCookieScope(opts);
|
|
79
|
+
const parts = ["Path=/", "Secure", "HttpOnly", "SameSite=Lax"];
|
|
80
|
+
if (domain)
|
|
81
|
+
parts.push(`Domain=${domain}`);
|
|
82
|
+
return parts.join("; ");
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=options.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"options.js","sourceRoot":"","sources":["../../../src/core/cookies/options.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAmBH;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAwB;IACzD,MAAM,KAAK,GAAgB,IAAI,CAAC,WAAW,IAAI,MAAM,CAAC;IACtD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IAE3B,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;QACrB,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CACb,mDAAmD;gBACjD,kEAAkE;gBAClE,yDAAyD;gBACzD,mDAAmD,CACtD,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CACb,mDAAmD;gBACjD,uEAAuE,CAC1E,CAAC;QACJ,CAAC;QACD,IAAI,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACtC,MAAM,IAAI,KAAK,CACb,wDAAwD;gBACtD,wCAAwC,CAC3C,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC;IAC/E,CAAC;IAED,aAAa;IACb,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CACb,6DAA6D;YAC3D,iDAAiD,CACpD,CAAC;IACJ,CAAC;IACD,OAAO;QACL,UAAU,EAAE,MAAM;QAClB,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE;QAC/B,MAAM,EAAE,SAAS;KAClB,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,IAAwB;IAKlD,MAAM,EAAE,MAAM,EAAE,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAC5C,OAAO;QACL,KAAK,EAAE,GAAG,MAAM,cAAc;QAC9B,GAAG,EAAE,GAAG,MAAM,UAAU;QACxB,SAAS,EAAE,GAAG,MAAM,gBAAgB;KACrC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAwB;IACvD,MAAM,EAAE,MAAM,EAAE,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAC5C,OAAO,GAAG,MAAM,aAAa,CAAC;AAChC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAAwB;IAC7D,MAAM,EAAE,MAAM,EAAE,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,cAAc,CAAC,CAAC;IAC/D,IAAI,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,UAAU,MAAM,EAAE,CAAC,CAAC;IAC3C,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
package/dist/core/index.d.ts
CHANGED
|
@@ -21,4 +21,6 @@ export type { DeriveSessionIdInput } from "./derive-session-id.js";
|
|
|
21
21
|
export { noBindingReason } from "./protect-policy.js";
|
|
22
22
|
export type { RequireProofOptions } from "./protect-policy.js";
|
|
23
23
|
export { parseCookieHeader } from "./protocol/cookies.js";
|
|
24
|
+
export { resolveCookieScope, cookieNames as resolveCookieNames, deviceCookieName, cookieAttributesString, } from "./cookies/options.js";
|
|
25
|
+
export type { CookieScope, CookieScopeOptions, CookieScopeResolved } from "./cookies/options.js";
|
|
24
26
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/core/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,cAAc,EACd,QAAQ,EACR,YAAY,EACZ,OAAO,EACP,SAAS,EACT,iBAAiB,EACjB,YAAY,EACZ,cAAc,EACd,WAAW,EACX,gBAAgB,EAChB,WAAW,EACX,aAAa,EACb,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,iBAAiB,EACjB,YAAY,EACZ,wBAAwB,EACxB,kBAAkB,EAClB,eAAe,EACf,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAErG,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEtE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,0BAA0B,EAC1B,yBAAyB,EACzB,oBAAoB,EACpB,yBAAyB,EACzB,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,0BAA0B,EAC1B,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC1F,YAAY,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAEhE,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAC5C,OAAO,EAAE,wBAAwB,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAC;AAEtG,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,YAAY,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAEnE,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,YAAY,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,cAAc,EACd,QAAQ,EACR,YAAY,EACZ,OAAO,EACP,SAAS,EACT,iBAAiB,EACjB,YAAY,EACZ,cAAc,EACd,WAAW,EACX,gBAAgB,EAChB,WAAW,EACX,aAAa,EACb,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,iBAAiB,EACjB,YAAY,EACZ,wBAAwB,EACxB,kBAAkB,EAClB,eAAe,EACf,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAErG,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEtE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,0BAA0B,EAC1B,yBAAyB,EACzB,oBAAoB,EACpB,yBAAyB,EACzB,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,0BAA0B,EAC1B,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC1F,YAAY,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAEhE,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAC5C,OAAO,EAAE,wBAAwB,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAC;AAEtG,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,YAAY,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAEnE,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,YAAY,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1D,OAAO,EACL,kBAAkB,EAClB,WAAW,IAAI,kBAAkB,EACjC,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dist/core/index.js
CHANGED
|
@@ -16,4 +16,5 @@ export { maybeEmitPolyfillMissing, POLYFILL_MISSING_GRACE_MS } from "./telemetry
|
|
|
16
16
|
export { deriveSessionId } from "./derive-session-id.js";
|
|
17
17
|
export { noBindingReason } from "./protect-policy.js";
|
|
18
18
|
export { parseCookieHeader } from "./protocol/cookies.js";
|
|
19
|
+
export { resolveCookieScope, cookieNames as resolveCookieNames, deviceCookieName, cookieAttributesString, } from "./cookies/options.js";
|
|
19
20
|
//# sourceMappingURL=index.js.map
|
package/dist/core/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAErG,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEtE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,0BAA0B,EAC1B,yBAAyB,EACzB,oBAAoB,EACpB,yBAAyB,EACzB,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,0BAA0B,EAC1B,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAG1F,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAC5C,OAAO,EAAE,wBAAwB,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAC;AAEtG,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGzD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAGtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAErG,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEtE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,0BAA0B,EAC1B,yBAAyB,EACzB,oBAAoB,EACpB,yBAAyB,EACzB,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,0BAA0B,EAC1B,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAG1F,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAC5C,OAAO,EAAE,wBAAwB,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAC;AAEtG,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGzD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAGtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1D,OAAO,EACL,kBAAkB,EAClB,WAAW,IAAI,kBAAkB,EACjC,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,sBAAsB,CAAC"}
|
package/dist/core/types.d.ts
CHANGED
|
@@ -157,13 +157,23 @@ export interface DbscOptions {
|
|
|
157
157
|
*/
|
|
158
158
|
refreshGraceMs?: number;
|
|
159
159
|
/**
|
|
160
|
-
* Cookie prefix scope. "host" (default) uses `__Host-` cookies —
|
|
161
|
-
* locked, no Domain attribute, strongest. "site" uses
|
|
162
|
-
*
|
|
163
|
-
* (app.example.com + api.example.com)
|
|
164
|
-
*
|
|
160
|
+
* Cookie prefix scope. `"host"` (default) uses `__Host-` cookies —
|
|
161
|
+
* origin-locked, no `Domain` attribute, strongest. `"site"` uses
|
|
162
|
+
* `__Secure-` cookies carrying `Domain=<cookieDomain>` so the binding works
|
|
163
|
+
* across subdomains (e.g. `app.example.com` + `api.example.com`). The
|
|
164
|
+
* `"site"` mode drops `__Host-`'s protection against a sibling subdomain
|
|
165
|
+
* setting or overwriting the cookie; only enable it when a same-origin
|
|
166
|
+
* deployment is genuinely not workable. See docs/integration-recipes.md.
|
|
165
167
|
*/
|
|
166
168
|
cookieScope?: "host" | "site";
|
|
169
|
+
/**
|
|
170
|
+
* Required when `cookieScope: "site"`. The `Domain` attribute attached to
|
|
171
|
+
* every DBSC cookie — typically the registrable apex (`example.com`) so the
|
|
172
|
+
* cookie is visible on every subdomain. Omit the leading dot. Throws at
|
|
173
|
+
* `dbsc()` / `createDbsc()` construction when `"site"` is set without it.
|
|
174
|
+
* Ignored in `"host"` mode.
|
|
175
|
+
*/
|
|
176
|
+
cookieDomain?: string;
|
|
167
177
|
rateLimiter?: RateLimiter;
|
|
168
178
|
/**
|
|
169
179
|
* Replay cache for per-request proofs (v2.8+). Without it, an attacker who
|
package/dist/core/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-dbsc.d.ts","sourceRoot":"","sources":["../../src/express/create-dbsc.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAE,KAAK,OAAO,EAAgB,KAAK,QAAQ,EAAE,KAAK,cAAc,EAAE,MAAM,SAAS,CAAC;AAGlG,OAAO,
|
|
1
|
+
{"version":3,"file":"create-dbsc.d.ts","sourceRoot":"","sources":["../../src/express/create-dbsc.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAE,KAAK,OAAO,EAAgB,KAAK,QAAQ,EAAE,KAAK,cAAc,EAAE,MAAM,SAAS,CAAC;AAGlG,OAAO,EAKL,KAAK,mBAAmB,EAEzB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAqB,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAqCxE,MAAM,WAAW,iBAAkB,SAAQ,kBAAkB;IAC3D,sFAAsF;IACtF,UAAU,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAC5B,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,OAAO;IACtB,yFAAyF;IACzF,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC;IAC/B,wDAAwD;IACxD,UAAU,IAAI,cAAc,CAAC;IAC7B,4FAA4F;IAC5F,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3E,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACxD,uEAAuE;IACvE,YAAY,CAAC,IAAI,CAAC,EAAE,mBAAmB,GAAG,cAAc,CAAC;CAC1D;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CA6D3D"}
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
import express from "express";
|
|
2
2
|
import { fileURLToPath } from "node:url";
|
|
3
3
|
import { randomBytes } from "node:crypto";
|
|
4
|
-
import { deriveSessionId, parseCookieHeader } from "../core/index.js";
|
|
4
|
+
import { deriveSessionId, parseCookieHeader, deviceCookieName, resolveCookieScope, } from "../core/index.js";
|
|
5
5
|
import { dbsc, bindSession } from "./index.js";
|
|
6
6
|
import { requireProof } from "./require-proof.js";
|
|
7
7
|
const DEVICE_COOKIE_TTL_MS = 365 * 24 * 60 * 60 * 1000;
|
|
8
8
|
/**
|
|
9
9
|
* Returns a stable per-device value for the JWT `bind()` path: reads the
|
|
10
|
-
*
|
|
11
|
-
* the same user thus derive distinct sessionIds and bind
|
|
10
|
+
* device cookie (named per cookie scope), or mints + sets one if absent. Two
|
|
11
|
+
* browsers of the same user thus derive distinct sessionIds and bind
|
|
12
|
+
* independently.
|
|
12
13
|
*/
|
|
13
|
-
function resolveDeviceHint(res,
|
|
14
|
-
const name =
|
|
14
|
+
function resolveDeviceHint(res, scope) {
|
|
15
|
+
const name = deviceCookieName(scope);
|
|
16
|
+
const { domain } = resolveCookieScope(scope);
|
|
15
17
|
const req = res.req;
|
|
16
18
|
const existing = req?.cookies?.[name] ??
|
|
17
19
|
parseCookieHeader(req?.headers?.cookie)[name];
|
|
@@ -20,10 +22,11 @@ function resolveDeviceHint(res, secure) {
|
|
|
20
22
|
const value = randomBytes(16).toString("hex");
|
|
21
23
|
res.cookie(name, value, {
|
|
22
24
|
httpOnly: true,
|
|
23
|
-
secure,
|
|
25
|
+
secure: scope.secure,
|
|
24
26
|
sameSite: "lax",
|
|
25
27
|
path: "/",
|
|
26
28
|
maxAge: DEVICE_COOKIE_TTL_MS,
|
|
29
|
+
...(domain !== undefined && { domain }),
|
|
27
30
|
});
|
|
28
31
|
return value;
|
|
29
32
|
}
|
|
@@ -34,6 +37,13 @@ function resolveDeviceHint(res, secure) {
|
|
|
34
37
|
*/
|
|
35
38
|
export function createDbsc(opts) {
|
|
36
39
|
const secure = opts.secure ?? true;
|
|
40
|
+
const cookieScope = opts.cookieScope;
|
|
41
|
+
const cookieDomain = opts.cookieDomain;
|
|
42
|
+
const scope = {
|
|
43
|
+
secure,
|
|
44
|
+
...(cookieScope !== undefined && { cookieScope }),
|
|
45
|
+
...(cookieDomain !== undefined && { cookieDomain }),
|
|
46
|
+
};
|
|
37
47
|
const clientPath = opts.clientPath ?? "/dbsc-client";
|
|
38
48
|
const registrationPath = opts.registrationPath ?? "/dbsc/registration";
|
|
39
49
|
const boundRegistrationPath = opts.boundRegistrationPath ?? "/dbsc-bound/registration";
|
|
@@ -48,7 +58,7 @@ export function createDbsc(opts) {
|
|
|
48
58
|
else {
|
|
49
59
|
// JWT path: no sessionId. An explicit deviceHint wins; otherwise the kit
|
|
50
60
|
// manages a per-device cookie so each browser binds independently.
|
|
51
|
-
const deviceHint = bindOpts.deviceHint ?? resolveDeviceHint(res,
|
|
61
|
+
const deviceHint = bindOpts.deviceHint ?? resolveDeviceHint(res, scope);
|
|
52
62
|
sessionId = await deriveSessionId({
|
|
53
63
|
userId: bindOpts.userId,
|
|
54
64
|
deviceHint,
|
|
@@ -58,6 +68,8 @@ export function createDbsc(opts) {
|
|
|
58
68
|
await bindSession(res, sessionId, opts.storage, {
|
|
59
69
|
userId: bindOpts.userId,
|
|
60
70
|
secure,
|
|
71
|
+
...(cookieScope !== undefined && { cookieScope }),
|
|
72
|
+
...(cookieDomain !== undefined && { cookieDomain }),
|
|
61
73
|
registrationPath,
|
|
62
74
|
...(opts.registrationCookieTtl !== undefined && {
|
|
63
75
|
registrationCookieTtl: opts.registrationCookieTtl,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-dbsc.js","sourceRoot":"","sources":["../../src/express/create-dbsc.ts"],"names":[],"mappings":"AAAA,OAAO,OAA2E,MAAM,SAAS,CAAC;AAClG,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,
|
|
1
|
+
{"version":3,"file":"create-dbsc.js","sourceRoot":"","sources":["../../src/express/create-dbsc.ts"],"names":[],"mappings":"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"}
|
package/dist/express/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Response, RequestHandler } from "express";
|
|
2
|
-
import { type DbscOptions, type StorageAdapter, type ProofReplayCache, type ProtectionTier, type SkippedEntry } from "../core/index.js";
|
|
2
|
+
import { type DbscOptions, type StorageAdapter, type ProofReplayCache, type ProtectionTier, type SkippedEntry, type CookieScope } from "../core/index.js";
|
|
3
3
|
export { requireBoundProof } from "./proof.js";
|
|
4
4
|
export type { RequireBoundProofOptions } from "./proof.js";
|
|
5
5
|
export { requireProof } from "./require-proof.js";
|
|
@@ -37,6 +37,10 @@ export interface BindSessionOptions {
|
|
|
37
37
|
userId: string;
|
|
38
38
|
/** Match the value passed to dbsc({ secure }). Defaults true. Mismatch = cookies the middleware cannot read. */
|
|
39
39
|
secure?: boolean;
|
|
40
|
+
/** Match the value passed to dbsc({ cookieScope }). Defaults "host". */
|
|
41
|
+
cookieScope?: CookieScope;
|
|
42
|
+
/** Match the value passed to dbsc({ cookieDomain }). Required for cookieScope: "site". */
|
|
43
|
+
cookieDomain?: string;
|
|
40
44
|
registrationPath?: string;
|
|
41
45
|
registrationCookieTtl?: number;
|
|
42
46
|
sessionTtl?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/express/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAW,QAAQ,EAAgB,cAAc,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/express/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAW,QAAQ,EAAgB,cAAc,EAAE,MAAM,SAAS,CAAC;AAC/E,OAAO,EAwBL,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,WAAW,EACjB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,YAAY,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,YAAY,EAAE,iBAAiB,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEhF,oFAAoF;AACpF,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,cAAc,CAAC;IACxB,MAAM,EAAE,OAAO,CAAC;IAChB,wEAAwE;IACxE,WAAW,CAAC,EAAE,gBAAgB,CAAC;CAChC;AACD,eAAO,MAAM,aAAa,EAAE,OAAO,MAAgD,CAAC;AAcpF,MAAM,WAAW,kBAAmB,SAAQ,WAAW;IACrD,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,UAAU;IACzB,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;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,OAAO,CAAC;QAChB,UAAU,MAAM;YACd,IAAI,EAAE,UAAU,CAAC;SAClB;KACF;CACF;AA0BD,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,gHAAgH;IAChH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,wEAAwE;IACxE,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,0FAA0F;IAC1F,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,wBAAsB,WAAW,CAC/B,GAAG,EAAE,QAAQ,EACb,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,IAAI,CAAC,CA8Cf;AAED,wBAAgB,IAAI,CAAC,IAAI,EAAE,kBAAkB,GAAG,cAAc,CAmhB7D"}
|
package/dist/express/index.js
CHANGED
|
@@ -1,23 +1,21 @@
|
|
|
1
|
-
import { handleRegistration, handleRefresh, handleBoundRegistration, handleBoundRefresh, issueChallenge, buildRegistrationHeader, buildChallengeHeader, readSessionResponseHeader, parseSessionSkippedHeader, REGISTRATION_HEADER, CHALLENGE_HEADER, LEGACY_REGISTRATION_HEADER, LEGACY_CHALLENGE_HEADER, NoopRateLimiter, emit, maybeEmitPolyfillMissing, parseCookieHeader, DbscProtocolError, DbscVerificationError, ErrorCodes, } from "../core/index.js";
|
|
1
|
+
import { handleRegistration, handleRefresh, handleBoundRegistration, handleBoundRefresh, issueChallenge, buildRegistrationHeader, buildChallengeHeader, readSessionResponseHeader, parseSessionSkippedHeader, REGISTRATION_HEADER, CHALLENGE_HEADER, LEGACY_REGISTRATION_HEADER, LEGACY_CHALLENGE_HEADER, NoopRateLimiter, emit, maybeEmitPolyfillMissing, parseCookieHeader, resolveCookieNames, cookieAttributesString, resolveCookieScope, DbscProtocolError, DbscVerificationError, ErrorCodes, } from "../core/index.js";
|
|
2
2
|
export { requireBoundProof } from "./proof.js";
|
|
3
3
|
export { requireProof } from "./require-proof.js";
|
|
4
4
|
export { createDbsc } from "./create-dbsc.js";
|
|
5
5
|
export const DBSC_INTERNAL = Symbol("dbsc-toolkit.express.internal");
|
|
6
|
-
const cookieNames = (
|
|
7
|
-
bound: secure ? "__Host-dbsc-session" : "dbsc-session",
|
|
8
|
-
reg: secure ? "__Host-dbsc-reg" : "dbsc-reg",
|
|
9
|
-
challenge: secure ? "__Host-dbsc-challenge" : "dbsc-challenge",
|
|
10
|
-
});
|
|
6
|
+
const cookieNames = (s) => resolveCookieNames(s);
|
|
11
7
|
const DEFAULT_BOUND_TTL = 10 * 60 * 1000;
|
|
12
8
|
const DEFAULT_REG_TTL = 24 * 60 * 60 * 1000;
|
|
13
9
|
const DEFAULT_SESSION_TTL = 24 * 60 * 60 * 1000;
|
|
14
|
-
function cookieOpts(ttlMs,
|
|
10
|
+
function cookieOpts(ttlMs, scope) {
|
|
11
|
+
const { domain } = resolveCookieScope(scope);
|
|
15
12
|
return {
|
|
16
13
|
httpOnly: true,
|
|
17
|
-
secure,
|
|
14
|
+
secure: scope.secure,
|
|
18
15
|
sameSite: "lax",
|
|
19
16
|
maxAge: ttlMs / 1000,
|
|
20
17
|
path: "/",
|
|
18
|
+
...(domain !== undefined && { domain }),
|
|
21
19
|
};
|
|
22
20
|
}
|
|
23
21
|
function serializeCookie(name, value, opts) {
|
|
@@ -29,6 +27,8 @@ function serializeCookie(name, value, opts) {
|
|
|
29
27
|
parts.push(`SameSite=${sameSite}`);
|
|
30
28
|
parts.push(`Max-Age=${opts.maxAge}`);
|
|
31
29
|
parts.push(`Path=${opts.path}`);
|
|
30
|
+
if (opts.domain)
|
|
31
|
+
parts.push(`Domain=${opts.domain}`);
|
|
32
32
|
return parts.join("; ");
|
|
33
33
|
}
|
|
34
34
|
export async function bindSession(res, sessionId, storage, opts) {
|
|
@@ -36,7 +36,12 @@ export async function bindSession(res, sessionId, storage, opts) {
|
|
|
36
36
|
const registrationPath = opts.registrationPath ?? "/dbsc/registration";
|
|
37
37
|
const regCookieTtl = opts.registrationCookieTtl ?? DEFAULT_REG_TTL;
|
|
38
38
|
const sessionTtl = opts.sessionTtl ?? DEFAULT_SESSION_TTL;
|
|
39
|
-
const
|
|
39
|
+
const scope = {
|
|
40
|
+
secure,
|
|
41
|
+
...(opts.cookieScope !== undefined && { cookieScope: opts.cookieScope }),
|
|
42
|
+
...(opts.cookieDomain !== undefined && { cookieDomain: opts.cookieDomain }),
|
|
43
|
+
};
|
|
44
|
+
const COOKIES = cookieNames(scope);
|
|
40
45
|
const existing = await storage.getSession(sessionId);
|
|
41
46
|
const now = Date.now();
|
|
42
47
|
if (!existing) {
|
|
@@ -65,13 +70,21 @@ export async function bindSession(res, sessionId, storage, opts) {
|
|
|
65
70
|
: [];
|
|
66
71
|
res.setHeader("Set-Cookie", [
|
|
67
72
|
...priorList,
|
|
68
|
-
serializeCookie(COOKIES.reg, sessionId, cookieOpts(regCookieTtl,
|
|
69
|
-
serializeCookie(COOKIES.challenge, challenge.jti, cookieOpts(5 * 60 * 1000,
|
|
73
|
+
serializeCookie(COOKIES.reg, sessionId, cookieOpts(regCookieTtl, scope)),
|
|
74
|
+
serializeCookie(COOKIES.challenge, challenge.jti, cookieOpts(5 * 60 * 1000, scope)),
|
|
70
75
|
]);
|
|
71
76
|
}
|
|
72
77
|
export function dbsc(opts) {
|
|
73
|
-
const { storage, registrationPath = "/dbsc/registration", refreshPath = "/dbsc/refresh", boundStatePath = "/dbsc-bound/state", boundChallengePath = "/dbsc-bound/challenge", boundRegistrationPath = "/dbsc-bound/registration", boundRefreshPath = "/dbsc-bound/refresh", boundCookieTtl = DEFAULT_BOUND_TTL, refreshGraceMs = 30_000, registrationCookieTtl = DEFAULT_REG_TTL, rateLimiter = new NoopRateLimiter(), replayCache, onEvent, autoBind, secure = true, } = opts;
|
|
74
|
-
const
|
|
78
|
+
const { storage, registrationPath = "/dbsc/registration", refreshPath = "/dbsc/refresh", boundStatePath = "/dbsc-bound/state", boundChallengePath = "/dbsc-bound/challenge", boundRegistrationPath = "/dbsc-bound/registration", boundRefreshPath = "/dbsc-bound/refresh", boundCookieTtl = DEFAULT_BOUND_TTL, refreshGraceMs = 30_000, registrationCookieTtl = DEFAULT_REG_TTL, rateLimiter = new NoopRateLimiter(), replayCache, onEvent, autoBind, secure = true, cookieScope, cookieDomain, } = opts;
|
|
79
|
+
const scope = {
|
|
80
|
+
secure,
|
|
81
|
+
...(cookieScope !== undefined && { cookieScope }),
|
|
82
|
+
...(cookieDomain !== undefined && { cookieDomain }),
|
|
83
|
+
};
|
|
84
|
+
// Fail-fast: rejects "site" without domain, mismatched secure flag, etc.
|
|
85
|
+
resolveCookieScope(scope);
|
|
86
|
+
const cookieAttrs = cookieAttributesString(scope);
|
|
87
|
+
const COOKIES = cookieNames(scope);
|
|
75
88
|
// Per-middleware-instance dedup set for the polyfill_missing telemetry event.
|
|
76
89
|
// Re-armed on process restart, which is fine: the signal is for ops alerting,
|
|
77
90
|
// not for security enforcement.
|
|
@@ -104,8 +117,8 @@ export function dbsc(opts) {
|
|
|
104
117
|
ip,
|
|
105
118
|
});
|
|
106
119
|
res.setHeader("Set-Cookie", [
|
|
107
|
-
serializeCookie(COOKIES.bound, sessionId, cookieOpts(boundCookieTtl,
|
|
108
|
-
serializeCookie(COOKIES.challenge, "", { ...cookieOpts(0,
|
|
120
|
+
serializeCookie(COOKIES.bound, sessionId, cookieOpts(boundCookieTtl, scope)),
|
|
121
|
+
serializeCookie(COOKIES.challenge, "", { ...cookieOpts(0, scope), maxAge: 0 }),
|
|
109
122
|
]);
|
|
110
123
|
res.setHeader("Content-Type", "application/json");
|
|
111
124
|
const origin = `${req.protocol}://${req.get("host")}`;
|
|
@@ -121,7 +134,7 @@ export function dbsc(opts) {
|
|
|
121
134
|
{
|
|
122
135
|
type: "cookie",
|
|
123
136
|
name: COOKIES.bound,
|
|
124
|
-
attributes:
|
|
137
|
+
attributes: cookieAttrs,
|
|
125
138
|
},
|
|
126
139
|
],
|
|
127
140
|
});
|
|
@@ -162,7 +175,7 @@ export function dbsc(opts) {
|
|
|
162
175
|
const challenge = await issueChallenge(sessionId, storage);
|
|
163
176
|
res.setHeader(CHALLENGE_HEADER, buildChallengeHeader(challenge.jti, sessionId));
|
|
164
177
|
res.setHeader(LEGACY_CHALLENGE_HEADER, buildChallengeHeader(challenge.jti, sessionId));
|
|
165
|
-
res.setHeader("Set-Cookie", serializeCookie(COOKIES.challenge, challenge.jti, cookieOpts(5 * 60 * 1000,
|
|
178
|
+
res.setHeader("Set-Cookie", serializeCookie(COOKIES.challenge, challenge.jti, cookieOpts(5 * 60 * 1000, scope)));
|
|
166
179
|
res.status(403).end();
|
|
167
180
|
return;
|
|
168
181
|
}
|
|
@@ -171,7 +184,7 @@ export function dbsc(opts) {
|
|
|
171
184
|
const challenge = await issueChallenge(sessionId, storage);
|
|
172
185
|
res.setHeader(CHALLENGE_HEADER, buildChallengeHeader(challenge.jti, sessionId));
|
|
173
186
|
res.setHeader(LEGACY_CHALLENGE_HEADER, buildChallengeHeader(challenge.jti, sessionId));
|
|
174
|
-
res.setHeader("Set-Cookie", serializeCookie(COOKIES.challenge, challenge.jti, cookieOpts(5 * 60 * 1000,
|
|
187
|
+
res.setHeader("Set-Cookie", serializeCookie(COOKIES.challenge, challenge.jti, cookieOpts(5 * 60 * 1000, scope)));
|
|
175
188
|
res.status(403).end();
|
|
176
189
|
return;
|
|
177
190
|
}
|
|
@@ -185,8 +198,8 @@ export function dbsc(opts) {
|
|
|
185
198
|
ip,
|
|
186
199
|
});
|
|
187
200
|
res.setHeader("Set-Cookie", [
|
|
188
|
-
serializeCookie(COOKIES.bound, sessionId, cookieOpts(boundCookieTtl,
|
|
189
|
-
serializeCookie(COOKIES.challenge, "", { ...cookieOpts(0,
|
|
201
|
+
serializeCookie(COOKIES.bound, sessionId, cookieOpts(boundCookieTtl, scope)),
|
|
202
|
+
serializeCookie(COOKIES.challenge, "", { ...cookieOpts(0, scope), maxAge: 0 }),
|
|
190
203
|
]);
|
|
191
204
|
res.setHeader("Content-Type", "application/json");
|
|
192
205
|
const origin = `${req.protocol}://${req.get("host")}`;
|
|
@@ -202,7 +215,7 @@ export function dbsc(opts) {
|
|
|
202
215
|
{
|
|
203
216
|
type: "cookie",
|
|
204
217
|
name: COOKIES.bound,
|
|
205
|
-
attributes:
|
|
218
|
+
attributes: cookieAttrs,
|
|
206
219
|
},
|
|
207
220
|
],
|
|
208
221
|
});
|
|
@@ -231,7 +244,7 @@ export function dbsc(opts) {
|
|
|
231
244
|
const challenge = await issueChallenge(sessionId, storage);
|
|
232
245
|
res.setHeader(CHALLENGE_HEADER, buildChallengeHeader(challenge.jti, sessionId));
|
|
233
246
|
res.setHeader(LEGACY_CHALLENGE_HEADER, buildChallengeHeader(challenge.jti, sessionId));
|
|
234
|
-
res.setHeader("Set-Cookie", serializeCookie(COOKIES.challenge, challenge.jti, cookieOpts(5 * 60 * 1000,
|
|
247
|
+
res.setHeader("Set-Cookie", serializeCookie(COOKIES.challenge, challenge.jti, cookieOpts(5 * 60 * 1000, scope)));
|
|
235
248
|
res.status(403).json({ error: err.message });
|
|
236
249
|
return;
|
|
237
250
|
}
|
|
@@ -339,7 +352,7 @@ export function dbsc(opts) {
|
|
|
339
352
|
ip,
|
|
340
353
|
});
|
|
341
354
|
res.setHeader("Set-Cookie", [
|
|
342
|
-
serializeCookie(COOKIES.bound, sessionId, cookieOpts(boundCookieTtl,
|
|
355
|
+
serializeCookie(COOKIES.bound, sessionId, cookieOpts(boundCookieTtl, scope)),
|
|
343
356
|
]);
|
|
344
357
|
res.status(200).json({
|
|
345
358
|
session_identifier: sessionId,
|
|
@@ -397,7 +410,7 @@ export function dbsc(opts) {
|
|
|
397
410
|
ip,
|
|
398
411
|
});
|
|
399
412
|
res.setHeader("Set-Cookie", [
|
|
400
|
-
serializeCookie(COOKIES.bound, sessionId, cookieOpts(boundCookieTtl,
|
|
413
|
+
serializeCookie(COOKIES.bound, sessionId, cookieOpts(boundCookieTtl, scope)),
|
|
401
414
|
]);
|
|
402
415
|
res.status(200).json({
|
|
403
416
|
session_identifier: sessionId,
|
|
@@ -470,7 +483,7 @@ export function dbsc(opts) {
|
|
|
470
483
|
if (sessionId)
|
|
471
484
|
await storage.revokeSession(sessionId);
|
|
472
485
|
res.setHeader("Set-Cookie", [
|
|
473
|
-
serializeCookie(COOKIES.bound, "", { ...cookieOpts(0,
|
|
486
|
+
serializeCookie(COOKIES.bound, "", { ...cookieOpts(0, scope), maxAge: 0 }),
|
|
474
487
|
]);
|
|
475
488
|
},
|
|
476
489
|
};
|
|
@@ -507,6 +520,8 @@ export function dbsc(opts) {
|
|
|
507
520
|
await bindSession(res, result.sessionId, storage, {
|
|
508
521
|
userId: result.userId,
|
|
509
522
|
secure,
|
|
523
|
+
...(cookieScope !== undefined && { cookieScope }),
|
|
524
|
+
...(cookieDomain !== undefined && { cookieDomain }),
|
|
510
525
|
registrationPath,
|
|
511
526
|
registrationCookieTtl,
|
|
512
527
|
});
|