@cedarjs/auth-dbauth-api 9.0.0-canary.1784 → 9.0.0-canary.3124

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/errors.js CHANGED
@@ -1,56 +1,3 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
- var errors_exports = {};
20
- __export(errors_exports, {
21
- CsrfTokenMismatchError: () => CsrfTokenMismatchError,
22
- DuplicateUsernameError: () => DuplicateUsernameError,
23
- FieldRequiredError: () => FieldRequiredError,
24
- FlowNotEnabledError: () => FlowNotEnabledError,
25
- GenericError: () => GenericError,
26
- IncorrectPasswordError: () => IncorrectPasswordError,
27
- MissingWebAuthnConfigError: () => MissingWebAuthnConfigError,
28
- NoForgotPasswordHandlerError: () => NoForgotPasswordHandlerError,
29
- NoLoginHandlerError: () => NoLoginHandlerError,
30
- NoResetPasswordHandlerError: () => NoResetPasswordHandlerError,
31
- NoSessionExpirationError: () => NoSessionExpirationError,
32
- NoSessionSecretError: () => NoSessionSecretError,
33
- NoSignupHandlerError: () => NoSignupHandlerError,
34
- NoUserIdError: () => NoUserIdError,
35
- NoWebAuthnConfigError: () => NoWebAuthnConfigError,
36
- NoWebAuthnSessionError: () => NoWebAuthnSessionError,
37
- NotLoggedInError: () => NotLoggedInError,
38
- PasswordRequiredError: () => PasswordRequiredError,
39
- PasswordValidationError: () => PasswordValidationError,
40
- ResetTokenExpiredError: () => ResetTokenExpiredError,
41
- ResetTokenInvalidError: () => ResetTokenInvalidError,
42
- ResetTokenRequiredError: () => ResetTokenRequiredError,
43
- ReusedPasswordError: () => ReusedPasswordError,
44
- SessionDecryptionError: () => SessionDecryptionError,
45
- UnknownAuthMethodError: () => UnknownAuthMethodError,
46
- UserNotFoundError: () => UserNotFoundError,
47
- UsernameAndPasswordRequiredError: () => UsernameAndPasswordRequiredError,
48
- UsernameNotFoundError: () => UsernameNotFoundError,
49
- UsernameRequiredError: () => UsernameRequiredError,
50
- WebAuthnError: () => WebAuthnError,
51
- WrongVerbError: () => WrongVerbError
52
- });
53
- module.exports = __toCommonJS(errors_exports);
54
1
  class NoSessionSecretError extends Error {
55
2
  constructor() {
56
3
  super(
@@ -165,10 +112,10 @@ class IncorrectPasswordError extends Error {
165
112
  this.name = "IncorrectPasswordError";
166
113
  }
167
114
  }
168
- class CsrfTokenMismatchError extends Error {
169
- constructor() {
170
- super(`CSRF token mismatch`);
171
- this.name = "CsrfTokenMismatchError";
115
+ class UntrustedOriginError extends Error {
116
+ constructor(message = "Request origin is not trusted") {
117
+ super(message);
118
+ this.name = "UntrustedOriginError";
172
119
  }
173
120
  }
174
121
  class SessionDecryptionError extends Error {
@@ -249,9 +196,7 @@ class NoWebAuthnSessionError extends WebAuthnError {
249
196
  this.name = "NoWebAuthnSessionError";
250
197
  }
251
198
  }
252
- // Annotate the CommonJS export names for ESM import in node:
253
- 0 && (module.exports = {
254
- CsrfTokenMismatchError,
199
+ export {
255
200
  DuplicateUsernameError,
256
201
  FieldRequiredError,
257
202
  FlowNotEnabledError,
@@ -276,10 +221,11 @@ class NoWebAuthnSessionError extends WebAuthnError {
276
221
  ReusedPasswordError,
277
222
  SessionDecryptionError,
278
223
  UnknownAuthMethodError,
224
+ UntrustedOriginError,
279
225
  UserNotFoundError,
280
226
  UsernameAndPasswordRequiredError,
281
227
  UsernameNotFoundError,
282
228
  UsernameRequiredError,
283
229
  WebAuthnError,
284
230
  WrongVerbError
285
- });
231
+ };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,7 @@
1
- export * from './DbAuthHandler';
2
- export { PasswordValidationError } from './errors';
3
- export * from './shared';
4
- export { authDecoder, createAuthDecoder } from './decoder';
1
+ export * from './DbAuthHandler.js';
2
+ export { PasswordValidationError } from './errors.js';
3
+ export * from './session.js';
4
+ export * from './shared.js';
5
+ export { authDecoder, createAuthDecoder } from './decoder.js';
6
+ export * from './originValidation.js';
5
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA;AAC/B,OAAO,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAA;AAClD,cAAc,UAAU,CAAA;AACxB,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAA;AAClC,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AACrD,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAC7D,cAAc,uBAAuB,CAAA"}
package/dist/index.js CHANGED
@@ -1,38 +1,11 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
19
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
- var src_exports = {};
21
- __export(src_exports, {
22
- PasswordValidationError: () => import_errors.PasswordValidationError,
23
- authDecoder: () => import_decoder.authDecoder,
24
- createAuthDecoder: () => import_decoder.createAuthDecoder
25
- });
26
- module.exports = __toCommonJS(src_exports);
27
- __reExport(src_exports, require("./DbAuthHandler"), module.exports);
28
- var import_errors = require("./errors");
29
- __reExport(src_exports, require("./shared"), module.exports);
30
- var import_decoder = require("./decoder");
31
- // Annotate the CommonJS export names for ESM import in node:
32
- 0 && (module.exports = {
1
+ export * from "./DbAuthHandler.js";
2
+ import { PasswordValidationError } from "./errors.js";
3
+ export * from "./session.js";
4
+ export * from "./shared.js";
5
+ import { authDecoder, createAuthDecoder } from "./decoder.js";
6
+ export * from "./originValidation.js";
7
+ export {
33
8
  PasswordValidationError,
34
9
  authDecoder,
35
- createAuthDecoder,
36
- ...require("./DbAuthHandler"),
37
- ...require("./shared")
38
- });
10
+ createAuthDecoder
11
+ };
@@ -0,0 +1,131 @@
1
+ import type { CorsConfig } from '@cedarjs/api';
2
+ /**
3
+ * Minimal, transport-agnostic shape of an incoming request needed to decide
4
+ * whether its `Origin` header should be trusted for a state-changing
5
+ * request. Deliberately decoupled from any specific request/event type (no
6
+ * `DbAuthHandler` coupling) so this helper can be reused by other handler
7
+ * packages.
8
+ */
9
+ export interface OriginValidationRequest {
10
+ /**
11
+ * HTTP method of the request, e.g. `GET`, `POST`. Used by
12
+ * {@link requiresOriginValidation} to decide whether a request needs to be
13
+ * checked at all.
14
+ */
15
+ method: string;
16
+ /**
17
+ * Request headers, including `origin` if the browser sent one.
18
+ */
19
+ headers: Headers;
20
+ /**
21
+ * Host (and port, if non-default) the request was sent to, resolved with
22
+ * {@link resolveRequestHost}. Used to allow same-origin requests through
23
+ * with no extra configuration, which covers the standard Cedar setup
24
+ * where the web side proxies API requests through its own origin. Pass
25
+ * `null` when the host can't be determined.
26
+ */
27
+ host?: string | null;
28
+ /**
29
+ * Scheme (`http`/`https`) the request is considered to have arrived
30
+ * over, resolved with {@link resolveRequestProtocol}, when it can be
31
+ * determined reliably. Used as an extra check alongside `host` when
32
+ * deciding whether the `Origin` header matches the request's own
33
+ * origin. Pass `null`/`undefined` when it can't be determined -- in that
34
+ * case only the host is compared, unless `proxied` narrows that further
35
+ * (see {@link isProxiedRequest}).
36
+ */
37
+ protocol?: string | null;
38
+ /**
39
+ * Whether the request declares itself as arriving through a forwarding
40
+ * proxy, resolved with {@link isProxiedRequest}. Scopes the
41
+ * unknown-scheme same-host restriction to requests a proxy actually
42
+ * touched -- see `isSameOrigin`.
43
+ */
44
+ proxied?: boolean;
45
+ }
46
+ export interface OriginValidationConfig {
47
+ /**
48
+ * Extra origins that are always trusted for state-changing requests, on
49
+ * top of the request's own host and any origins already listed in
50
+ * `cors.origin`.
51
+ */
52
+ trustedOrigins?: string | string[];
53
+ /**
54
+ * The `origin` value from a handler's `cors` config (same shape as passed
55
+ * to `createCorsContext`). String and array values are treated as
56
+ * trusted origins.
57
+ *
58
+ * `true` (reflect any request origin back in
59
+ * `Access-Control-Allow-Origin`) is intentionally NOT treated as trust --
60
+ * combined with `credentials: true` that is the exact misconfiguration
61
+ * this check protects against. Apps that need to accept requests from an
62
+ * arbitrary set of origins must list them explicitly in `trustedOrigins`
63
+ * instead.
64
+ */
65
+ corsOrigin?: CorsConfig['origin'];
66
+ }
67
+ /**
68
+ * HTTP methods that can change server-side state and therefore need their
69
+ * `Origin` validated. `GET` and `HEAD` requests are read-only and are never
70
+ * checked.
71
+ */
72
+ export declare function requiresOriginValidation(method: string): boolean;
73
+ /**
74
+ * Resolves the host a request should be considered as having arrived at,
75
+ * preferring a forwarding proxy's advertised host over the connection-level
76
+ * one.
77
+ *
78
+ * A proxy in front of the api side (this framework's own `cedar serve
79
+ * --ud`, or an external nginx/CDN) terminates the browser's connection and
80
+ * opens a new one to the api server, so the request's own URL/`Host` header
81
+ * reflects that internal hop rather than the origin-facing host the
82
+ * browser actually targeted. `X-Forwarded-Host` carries the origin-facing
83
+ * host instead.
84
+ *
85
+ * Trusting `X-Forwarded-Host` here is safe for CSRF purposes: a cross-site
86
+ * HTML form can't set arbitrary request headers, and a cross-origin
87
+ * `fetch()` that sets a custom header triggers a CORS preflight, so an
88
+ * attacker can't forge it without already having crossed the browser's
89
+ * CORS checks.
90
+ *
91
+ * @param url - The request's own URL (Fetch API requests only), used as a
92
+ * fallback when neither `X-Forwarded-Host` nor `Host` is present.
93
+ */
94
+ export declare function resolveRequestHost(headers: Headers, url?: string | null): string | null;
95
+ /**
96
+ * Resolves the scheme (`http`/`https`) a request should be considered as
97
+ * having arrived over, mirroring {@link resolveRequestHost}.
98
+ *
99
+ * The request's own URL is only used as a fallback when no
100
+ * `X-Forwarded-Host` is present -- once a proxy has declared itself by
101
+ * setting that header, the request's own URL reflects the internal hop to
102
+ * the proxy, and its scheme can't be assumed to match what the browser
103
+ * actually used unless the proxy also set `X-Forwarded-Proto`.
104
+ *
105
+ * @param url - The request's own URL (Fetch API requests only).
106
+ */
107
+ export declare function resolveRequestProtocol(headers: Headers, url?: string | null): string | null;
108
+ /**
109
+ * Whether a request declares itself as arriving through a forwarding
110
+ * proxy, i.e. carries an `X-Forwarded-Host` header.
111
+ *
112
+ * Used to scope the unknown-scheme same-host restriction (see
113
+ * `isSameOrigin`) to requests a proxy actually touched. A request with no
114
+ * forwarding headers at all is a direct connection -- the normal case for
115
+ * dev servers, classic `cedar serve`, and most self-hosts -- not evidence
116
+ * of a proxy.
117
+ */
118
+ export declare function isProxiedRequest(headers: Headers): boolean;
119
+ /**
120
+ * Decides whether a request's `Origin` header should be trusted.
121
+ *
122
+ * Requests with no `Origin` header are always trusted: non-browser clients
123
+ * (server-to-server calls, CLIs, mobile apps) don't send one and don't carry
124
+ * ambient browser cookies, so they aren't CSRF vectors.
125
+ *
126
+ * When an `Origin` header is present, it's trusted when it matches the
127
+ * request's own host, is listed in `trustedOrigins`, or is listed in
128
+ * `corsOrigin`. Everything else is untrusted.
129
+ */
130
+ export declare function isRequestOriginTrusted(request: OriginValidationRequest, config: OriginValidationConfig): boolean;
131
+ //# sourceMappingURL=originValidation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"originValidation.d.ts","sourceRoot":"","sources":["../src/originValidation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAE9C;;;;;;GAMG;AACH,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,MAAM,EAAE,MAAM,CAAA;IACd;;OAEG;IACH,OAAO,EAAE,OAAO,CAAA;IAChB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IAClC;;;;;;;;;;;OAWG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAA;CAClC;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAGhE;AAgBD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,OAAO,EAChB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,GAClB,MAAM,GAAG,IAAI,CAoBf;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,OAAO,EAChB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,GAClB,MAAM,GAAG,IAAI,CAef;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAE1D;AA+CD;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,uBAAuB,EAChC,MAAM,EAAE,sBAAsB,GAC7B,OAAO,CA6BT"}
@@ -0,0 +1,92 @@
1
+ function requiresOriginValidation(method) {
2
+ const upperMethod = method.toUpperCase();
3
+ return upperMethod !== "GET" && upperMethod !== "HEAD";
4
+ }
5
+ function toOriginList(value) {
6
+ if (!value) {
7
+ return [];
8
+ }
9
+ return Array.isArray(value) ? value : [value];
10
+ }
11
+ function firstForwardedValue(headerValue) {
12
+ return headerValue.split(",")[0].trim();
13
+ }
14
+ function resolveRequestHost(headers, url) {
15
+ const forwardedHost = headers.get("x-forwarded-host");
16
+ if (forwardedHost) {
17
+ return firstForwardedValue(forwardedHost);
18
+ }
19
+ const host = headers.get("host");
20
+ if (host) {
21
+ return host;
22
+ }
23
+ if (url) {
24
+ try {
25
+ return new URL(url).host;
26
+ } catch {
27
+ return null;
28
+ }
29
+ }
30
+ return null;
31
+ }
32
+ function resolveRequestProtocol(headers, url) {
33
+ const forwardedProto = headers.get("x-forwarded-proto");
34
+ if (forwardedProto) {
35
+ return firstForwardedValue(forwardedProto).toLowerCase();
36
+ }
37
+ if (!headers.get("x-forwarded-host") && url) {
38
+ try {
39
+ return new URL(url).protocol.replace(":", "");
40
+ } catch {
41
+ return null;
42
+ }
43
+ }
44
+ return null;
45
+ }
46
+ function isProxiedRequest(headers) {
47
+ return headers.get("x-forwarded-host") !== null;
48
+ }
49
+ function isSameOrigin(origin, host, protocol, proxied) {
50
+ try {
51
+ const originUrl = new URL(origin);
52
+ if (originUrl.host !== host) {
53
+ return false;
54
+ }
55
+ if (protocol) {
56
+ return originUrl.protocol === `${protocol}:`;
57
+ }
58
+ if (proxied) {
59
+ return originUrl.protocol === "https:";
60
+ }
61
+ return true;
62
+ } catch {
63
+ return false;
64
+ }
65
+ }
66
+ function isRequestOriginTrusted(request, config) {
67
+ const origin = request.headers.get("origin");
68
+ if (!origin) {
69
+ return true;
70
+ }
71
+ if (request.host && isSameOrigin(origin, request.host, request.protocol, request.proxied)) {
72
+ return true;
73
+ }
74
+ const trustedOrigins = toOriginList(config.trustedOrigins);
75
+ if (trustedOrigins.includes(origin)) {
76
+ return true;
77
+ }
78
+ const corsOrigins = toOriginList(
79
+ typeof config.corsOrigin === "string" || Array.isArray(config.corsOrigin) ? config.corsOrigin : void 0
80
+ );
81
+ if (corsOrigins.includes(origin)) {
82
+ return true;
83
+ }
84
+ return false;
85
+ }
86
+ export {
87
+ isProxiedRequest,
88
+ isRequestOriginTrusted,
89
+ requiresOriginValidation,
90
+ resolveRequestHost,
91
+ resolveRequestProtocol
92
+ };
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Cookie attributes that can be set on a dbAuth cookie, either as
3
+ * `cookie.attributes` or (deprecated) directly on `cookie`.
4
+ */
5
+ export interface DbAuthCookieAttributes {
6
+ Path?: string;
7
+ HttpOnly?: boolean;
8
+ Secure?: boolean;
9
+ SameSite?: string;
10
+ Domain?: string;
11
+ }
12
+ /**
13
+ * Configuration for the cookies dbAuth sets: the session cookie's name, and
14
+ * the attributes applied to every cookie dbAuth writes (the session cookie
15
+ * and the `auth-provider` cookie).
16
+ */
17
+ export interface DbAuthCookieConfig extends DbAuthCookieAttributes {
18
+ attributes?: DbAuthCookieAttributes;
19
+ /**
20
+ * The name of the cookie that dbAuth sets
21
+ *
22
+ * %port% will be replaced with the port the api server is running on.
23
+ * If you have multiple RW apps running on the same host, you'll need to
24
+ * make sure they all use unique cookie names
25
+ */
26
+ name?: string;
27
+ }
28
+ /**
29
+ * Returns a UTC date string `expiresInSeconds` seconds in the future. Used as
30
+ * the `Expires` cookie attribute for a session that should stay valid for
31
+ * that long from now.
32
+ */
33
+ export declare function createExpiresAtDate(expiresInSeconds: number): string;
34
+ /**
35
+ * Generates a new CSRF token (a standard UUID) to pair with a session.
36
+ */
37
+ export declare function createCsrfToken(): string;
38
+ /**
39
+ * Removes any fields not explicitly allowed to be sent to the client before
40
+ * sending a user record over the wire.
41
+ */
42
+ export declare function sanitizeUser(user: Record<string, unknown>, allowedUserFields: string[]): Record<string, unknown>;
43
+ /**
44
+ * Builds the Set-Cookie attribute strings (`Path`, `HttpOnly`, `SameSite`,
45
+ * `Secure`, `Domain`, `Expires`) for a dbAuth cookie.
46
+ *
47
+ * Pass `expires: 'now'` (the default) to get the attributes needed to expire
48
+ * the cookie, or a UTC date string (e.g. from `createExpiresAtDate`) to set a
49
+ * future expiration.
50
+ */
51
+ export declare function buildCookieAttributes({ cookieConfig, expires, overrideAttributes, }: {
52
+ cookieConfig?: DbAuthCookieConfig;
53
+ expires?: 'now' | string;
54
+ overrideAttributes?: DbAuthCookieAttributes;
55
+ }): string[];
56
+ /**
57
+ * Builds the Set-Cookie header string for the `auth-provider` cookie dbAuth
58
+ * sets alongside the session cookie.
59
+ */
60
+ export declare function createAuthProviderCookieString({ cookieConfig, expiresAt, }: {
61
+ cookieConfig?: DbAuthCookieConfig;
62
+ expiresAt: string;
63
+ }): string;
64
+ /**
65
+ * Builds the Set-Cookie header string for the dbAuth session cookie: the
66
+ * `data;csrfToken` payload, encrypted, under the configured cookie name and
67
+ * attributes.
68
+ */
69
+ export declare function createSessionCookieString<TIdType = unknown>({ data, csrfToken, cookieConfig, expiresAt, }: {
70
+ data: Record<string, TIdType>;
71
+ csrfToken: string;
72
+ cookieConfig?: DbAuthCookieConfig;
73
+ expiresAt: string;
74
+ }): string;
75
+ /** Fields returned from the user record when none are explicitly allowed */
76
+ export declare const DEFAULT_ALLOWED_USER_FIELDS: string[];
77
+ export interface CreateLoginResponseOptions {
78
+ /**
79
+ * Object containing cookie config options: the cookie name (with %port%
80
+ * support) and the attributes applied to it (`Path`, `HttpOnly`,
81
+ * `SameSite`, `Secure`, `Domain`).
82
+ */
83
+ cookie?: DbAuthCookieConfig;
84
+ /**
85
+ * The fields that are allowed to be returned from the user record.
86
+ * Defaults to `id` and `email`.
87
+ */
88
+ allowedUserFields?: string[];
89
+ /**
90
+ * The `Expires` cookie attribute value for the session and `auth-provider`
91
+ * cookies: a UTC date string in the future. Build one with
92
+ * `createExpiresAtDate(expiresInSeconds)`.
93
+ */
94
+ expiresAt: string;
95
+ /**
96
+ * The HTTP status code to return in the response tuple. Defaults to 200.
97
+ */
98
+ statusCode?: number;
99
+ }
100
+ /**
101
+ * Mints a dbAuth session for the given user: a CSRF token, a session cookie
102
+ * (the sanitized user data paired with the CSRF token, encrypted), and the
103
+ * `auth-provider` cookie, in the same `[body, headers, { statusCode }]` shape
104
+ * every dbAuth auth method returns.
105
+ *
106
+ * Callable without a `DbAuthHandler` instance, so any code that has already
107
+ * verified a user's identity — a WebAuthn assertion, an OAuth callback, a
108
+ * magic link — can issue a session the same way the built-in login flow
109
+ * does.
110
+ */
111
+ export declare function createLoginResponse(user: Record<string, unknown>, options: CreateLoginResponseOptions): [Record<string, unknown>, Headers, {
112
+ statusCode: number;
113
+ }];
114
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACrC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAmB,SAAQ,sBAAsB;IAChE,UAAU,CAAC,EAAE,sBAAsB,CAAA;IACnC;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAOD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,gBAAgB,EAAE,MAAM,GAAG,MAAM,CAKpE;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,iBAAiB,EAAE,MAAM,EAAE,GAC1B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAUzB;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,YAAY,EACZ,OAAe,EACf,kBAAuB,GACxB,EAAE;IACD,YAAY,CAAC,EAAE,kBAAkB,CAAA;IACjC,OAAO,CAAC,EAAE,KAAK,GAAG,MAAM,CAAA;IACxB,kBAAkB,CAAC,EAAE,sBAAsB,CAAA;CAC5C,GAAG,MAAM,EAAE,CAiCX;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,CAAC,EAC7C,YAAY,EACZ,SAAS,GACV,EAAE;IACD,YAAY,CAAC,EAAE,kBAAkB,CAAA;IACjC,SAAS,EAAE,MAAM,CAAA;CAClB,GAAG,MAAM,CAKT;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,GAAG,OAAO,EAAE,EAC3D,IAAI,EACJ,SAAS,EACT,YAAY,EACZ,SAAS,GACV,EAAE;IACD,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,CAAC,EAAE,kBAAkB,CAAA;IACjC,SAAS,EAAE,MAAM,CAAA;CAClB,GAAG,MAAM,CAQT;AAED,4EAA4E;AAC5E,eAAO,MAAM,2BAA2B,UAAkB,CAAA;AAE1D,MAAM,WAAW,0BAA0B;IACzC;;;;OAIG;IACH,MAAM,CAAC,EAAE,kBAAkB,CAAA;IAC3B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC5B;;;;OAIG;IACH,SAAS,EAAE,MAAM,CAAA;IACjB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,EAAE,0BAA0B,GAClC,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CA+B5D"}
@@ -0,0 +1,103 @@
1
+ import { v4 as uuidv4 } from "uuid";
2
+ import { encryptSession, generateCookieName } from "./shared.js";
3
+ const PAST_EXPIRES_DATE = (/* @__PURE__ */ new Date(
4
+ "1970-01-01T00:00:00.000+00:00"
5
+ )).toUTCString();
6
+ function createExpiresAtDate(expiresInSeconds) {
7
+ const expiresAt = /* @__PURE__ */ new Date();
8
+ expiresAt.setSeconds(expiresAt.getSeconds() + expiresInSeconds);
9
+ return expiresAt.toUTCString();
10
+ }
11
+ function createCsrfToken() {
12
+ return uuidv4();
13
+ }
14
+ function sanitizeUser(user, allowedUserFields) {
15
+ const sanitized = JSON.parse(JSON.stringify(user));
16
+ Object.keys(sanitized).forEach((key) => {
17
+ if (!allowedUserFields.includes(key)) {
18
+ delete sanitized[key];
19
+ }
20
+ });
21
+ return sanitized;
22
+ }
23
+ function buildCookieAttributes({
24
+ cookieConfig,
25
+ expires = "now",
26
+ overrideAttributes = {}
27
+ }) {
28
+ const userCookieAttributes = cookieConfig?.attributes ? { ...cookieConfig.attributes } : { ...cookieConfig };
29
+ if (!cookieConfig?.attributes) {
30
+ delete userCookieAttributes.name;
31
+ }
32
+ const cookieOptions = { ...userCookieAttributes, ...overrideAttributes };
33
+ const meta = Object.keys(cookieOptions).map((key) => {
34
+ const optionValue = cookieOptions[key];
35
+ if (optionValue === true) {
36
+ return key;
37
+ } else if (optionValue === false) {
38
+ return null;
39
+ } else {
40
+ return `${key}=${optionValue}`;
41
+ }
42
+ }).filter((v) => v !== null);
43
+ const expiresAt = expires === "now" ? PAST_EXPIRES_DATE : expires;
44
+ meta.push(`Expires=${expiresAt}`);
45
+ return meta;
46
+ }
47
+ function createAuthProviderCookieString({
48
+ cookieConfig,
49
+ expiresAt
50
+ }) {
51
+ return [
52
+ `auth-provider=dbAuth`,
53
+ ...buildCookieAttributes({ cookieConfig, expires: expiresAt })
54
+ ].join(";");
55
+ }
56
+ function createSessionCookieString({
57
+ data,
58
+ csrfToken,
59
+ cookieConfig,
60
+ expiresAt
61
+ }) {
62
+ const session = JSON.stringify(data) + ";" + csrfToken;
63
+ const encrypted = encryptSession(session);
64
+ return [
65
+ `${generateCookieName(cookieConfig?.name)}=${encrypted}`,
66
+ ...buildCookieAttributes({ cookieConfig, expires: expiresAt })
67
+ ].join(";");
68
+ }
69
+ const DEFAULT_ALLOWED_USER_FIELDS = ["id", "email"];
70
+ function createLoginResponse(user, options) {
71
+ const allowedUserFields = options.allowedUserFields ?? DEFAULT_ALLOWED_USER_FIELDS;
72
+ const sessionData = sanitizeUser(user, allowedUserFields);
73
+ const csrfToken = createCsrfToken();
74
+ const headers = new Headers();
75
+ headers.append("csrf-token", csrfToken);
76
+ headers.append(
77
+ "set-cookie",
78
+ createAuthProviderCookieString({
79
+ cookieConfig: options.cookie,
80
+ expiresAt: options.expiresAt
81
+ })
82
+ );
83
+ headers.append(
84
+ "set-cookie",
85
+ createSessionCookieString({
86
+ data: sessionData,
87
+ csrfToken,
88
+ cookieConfig: options.cookie,
89
+ expiresAt: options.expiresAt
90
+ })
91
+ );
92
+ return [sessionData, headers, { statusCode: options.statusCode ?? 200 }];
93
+ }
94
+ export {
95
+ DEFAULT_ALLOWED_USER_FIELDS,
96
+ buildCookieAttributes,
97
+ createAuthProviderCookieString,
98
+ createCsrfToken,
99
+ createExpiresAtDate,
100
+ createLoginResponse,
101
+ createSessionCookieString,
102
+ sanitizeUser
103
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../src/shared.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAEtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAM/C,KAAK,aAAa,GAAG;IACnB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,CAAC,CAAC,EAAE,MAAM,CAAA;IACV,CAAC,CAAC,EAAE,MAAM,CAAA;IACV,CAAC,CAAC,EAAE,MAAM,CAAA;IACV,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AA+ED,eAAO,MAAM,aAAa,GAAI,OAAO,oBAAoB,GAAG,OAAO,QAElE,CAAA;AAGD,eAAO,MAAM,eAAe,GAAI,MAAM,MAAM,GAAG,SAAS,YAOvD,CAAA;AAGD,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,GAAG,IAAI,UAiCjD,CAAA;AAED,eAAO,MAAM,cAAc,GAAI,YAAY,MAAM,WAWhD,CAAA;AAGD,eAAO,MAAM,UAAU,GACrB,MAAM,MAAM,GAAG,SAAS,EACxB,oBAAoB,MAAM,GAAG,SAAS,kBAkBvC,CAAA;AAKD,eAAO,MAAM,aAAa,GACxB,OAAO,oBAAoB,GAAG,OAAO,EACrC,oBAAoB,MAAM,GAAG,SAAS,QAavC,CAAA;AAED,eAAO,MAAM,eAAe,GAAI,OAAO,oBAAoB,GAAG,OAAO,QAgBpE,CAAA;AAED,eAAO,MAAM,SAAS,GAAI,OAAO,MAAM,WAEtC,CAAA;AAMD,eAAO,MAAM,YAAY,GACvB,MAAM,MAAM,EACZ,qBAGG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,aAAa,CAAA;CAAO,aAWnD,CAAA;AAID,eAAO,MAAM,kBAAkB,GAAI,MAAM,MAAM,EAAE,OAAO,MAAM,aAM7D,CAAA;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,UAK9D;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,oBAAoB,GAAG,OAAO,IAGnC,UAAU;IACR,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,EACD,aAAa,WAAW;gBAQV,MAAM;aACT,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;wBACtB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;WACrC,MAAM;EA2BlB;AAYD,eAAO,MAAM,qBAAqB,GAAI,MAAM,MAAM,KAAG,aAYpD,CAAA"}
1
+ {"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../src/shared.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAEtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAM/C,KAAK,aAAa,GAAG;IACnB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,CAAC,CAAC,EAAE,MAAM,CAAA;IACV,CAAC,CAAC,EAAE,MAAM,CAAA;IACV,CAAC,CAAC,EAAE,MAAM,CAAA;IACV,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AA6ED,eAAO,MAAM,aAAa,GAAI,OAAO,oBAAoB,GAAG,OAAO,QAElE,CAAA;AAGD,eAAO,MAAM,eAAe,GAAI,MAAM,MAAM,GAAG,SAAS,YAOvD,CAAA;AAGD,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,GAAG,IAAI,UAiCjD,CAAA;AAED,eAAO,MAAM,cAAc,GAAI,YAAY,MAAM,WAWhD,CAAA;AAGD,eAAO,MAAM,UAAU,GACrB,MAAM,MAAM,GAAG,SAAS,EACxB,oBAAoB,MAAM,GAAG,SAAS,kBAkBvC,CAAA;AAKD,eAAO,MAAM,aAAa,GACxB,OAAO,oBAAoB,GAAG,OAAO,EACrC,oBAAoB,MAAM,GAAG,SAAS,QAavC,CAAA;AAED,eAAO,MAAM,eAAe,GAAI,OAAO,oBAAoB,GAAG,OAAO,QAgBpE,CAAA;AAED,eAAO,MAAM,SAAS,GAAI,OAAO,MAAM,WAEtC,CAAA;AAMD,eAAO,MAAM,YAAY,GACvB,MAAM,MAAM,EACZ,qBAGG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,aAAa,CAAA;CAAO,aAWnD,CAAA;AAID,eAAO,MAAM,kBAAkB,GAAI,MAAM,MAAM,EAAE,OAAO,MAAM,aAM7D,CAAA;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,UAK9D;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,oBAAoB,GAAG,OAAO,IAGnC,UAAU;IACR,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,EACD,aAAa,WAAW;gBAQV,MAAM;aACT,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;wBACtB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;WACrC,MAAM;EA2BlB;AAYD,eAAO,MAAM,qBAAqB,GAAI,MAAM,MAAM,KAAG,aAYpD,CAAA"}