@dbx-tools/tunnel 0.6.89 → 0.6.91
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 +22 -31
- package/index.ts +2 -6
- package/lib/index.d.ts +2 -6
- package/lib/index.js +3 -6
- package/lib/src/allowlist.d.ts +1 -1
- package/lib/src/allowlist.js +2 -2
- package/lib/src/gate.d.ts +12 -9
- package/lib/src/gate.js +60 -82
- package/lib/src/interceptor.d.ts +1 -1
- package/lib/src/interceptor.js +2 -2
- package/lib/src/plugin.d.ts +45 -32
- package/lib/src/plugin.js +104 -72
- package/lib/src/signing-key.d.ts +2 -2
- package/lib/src/signing-key.js +4 -4
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -8
- package/src/allowlist.ts +1 -1
- package/src/gate.ts +64 -95
- package/src/interceptor.ts +1 -1
- package/src/plugin.ts +142 -93
- package/src/signing-key.ts +3 -3
- package/lib/src/otp.d.ts +0 -49
- package/lib/src/otp.js +0 -130
- package/lib/src/rate-limit.d.ts +0 -35
- package/lib/src/rate-limit.js +0 -53
- package/src/otp.ts +0 -143
- package/src/rate-limit.ts +0 -59
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# @dbx-tools/tunnel
|
|
2
2
|
|
|
3
|
-
Front an app with a public tunnel and
|
|
4
|
-
in-process.
|
|
3
|
+
Front an app with a public tunnel and the passwordless
|
|
4
|
+
[`@dbx-tools/auth`](../auth) gate, in-process.
|
|
5
5
|
|
|
6
6
|
Built on the [SSE-enabled Portr fork](https://github.com/reggie-db/portr/releases/tag/v1.0.15-sse.2),
|
|
7
7
|
based on [upstream Portr](https://github.com/amalshaji/portr). Use this library
|
|
@@ -18,9 +18,9 @@ context: `createApp({ interceptor: tunnelInterceptor() })` applies the computed
|
|
|
18
18
|
so the app and portr live and die as one (concurrently-style - signals pass
|
|
19
19
|
through, either death tears the pair down). The app is the process; the tunnel
|
|
20
20
|
rides along inside it. Access is granted per email address against an allow-list,
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
authenticated by Better Auth email OTP or a passkey; the gate itself is the
|
|
22
|
+
`authGate` AppKit plugin, which registers the login routes and a gating
|
|
23
|
+
middleware on the app's OWN Express server (no separate proxy process).
|
|
24
24
|
|
|
25
25
|
**Key features:**
|
|
26
26
|
|
|
@@ -56,27 +56,19 @@ gating middleware on the app's OWN Express server (no separate proxy process).
|
|
|
56
56
|
`EMAIL_SYSTEM_FROM`), never a person's address, since a reply to a
|
|
57
57
|
machine-generated code reaches nobody. `EMAIL_FROM` is not required - see
|
|
58
58
|
[`@dbx-tools/email`](../../node/email#sender-addresses).
|
|
59
|
-
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
rest at boot, and skips entirely when nothing is bound rather than creating
|
|
69
|
-
infrastructure on someone else's behalf.
|
|
70
|
-
- HS256 session JWT (via `jose`) carrying only the email, signed with a key that
|
|
71
|
-
is PERSISTED in AppKit's cache for 30 days - so a signed-in browser stays signed
|
|
72
|
-
in across the restarts a tunnel sees whenever the app it wraps reloads. An
|
|
73
|
-
operator-held `TUNNEL_AUTH_JWT_SECRET` still wins. `TUNNEL_AUTH_SESSION_CUTOFF`
|
|
74
|
-
is the log-everyone-out switch, and takes a relative duration (`-30d`) as
|
|
75
|
-
readily as a date.
|
|
59
|
+
- Better Auth owns users, hashed OTP verification records, sessions, rate
|
|
60
|
+
limits, and passkey credentials. `@dbx-tools/tunnel` supplies only its
|
|
61
|
+
authorization policy, branded email delivery, and transport boundary.
|
|
62
|
+
- Storage is the native AppKit `lakebase()` pool when registered, or SQLite in
|
|
63
|
+
the operating system's application-data directory. Both adapters run Better
|
|
64
|
+
Auth's own migrations under a Postgres advisory lock or file lock.
|
|
65
|
+
- Email OTP remains bootstrap and recovery. Returning users can authenticate
|
|
66
|
+
with discoverable passkeys, enroll multiple devices, and name or remove them
|
|
67
|
+
through [`@dbx-tools/ui-auth`](../../ui/auth).
|
|
76
68
|
- Allow-list patterns in three shapes, matched in order: a domain shortcut
|
|
77
69
|
(`example.com`, `@example.com`), a shell-style glob (`*@example.com`), or a
|
|
78
70
|
regex literal (`/^ops-.*@example\.com$/`). An empty list allows nobody.
|
|
79
|
-
-
|
|
71
|
+
- Better Auth rate limiting plus anti-enumeration: the compatibility code
|
|
80
72
|
request always answers `{ ok: true }`, whether or not the address is allowed.
|
|
81
73
|
- Inbound `x-` headers are stripped by default and re-allowed by pattern, so a
|
|
82
74
|
public caller cannot spoof the headers the app trusts - above all
|
|
@@ -373,16 +365,15 @@ the selected release and executable path, then removes the temporary directory.
|
|
|
373
365
|
|
|
374
366
|
- `interceptor` - `tunnelInterceptor()`, the `createApp` interceptor that applies
|
|
375
367
|
`DATABRICKS_HOST`, launches portr, and binds it to the app.
|
|
376
|
-
- `plugin` - `authGate()`,
|
|
377
|
-
and
|
|
368
|
+
- `plugin` - `authGate()`, authorization/delivery config, Better Auth
|
|
369
|
+
composition, and AppKit Lakebase discovery.
|
|
378
370
|
- `gate` - the login routes + gating middleware (`mountGate`, `isTunnelHost`):
|
|
379
371
|
`Host`-based tunnel classification, session enforcement, and identity injection.
|
|
380
372
|
- `send-code` - the default OTP delivery through the shared email transport
|
|
381
373
|
(lazily imported) and the SMTP fail-fast.
|
|
382
374
|
- `code-email` - pure builders for the code email's subject/preheader/bodies.
|
|
383
|
-
- `
|
|
384
|
-
|
|
385
|
-
re-read convergence) and the `TUNNEL_AUTH_SESSION_CUTOFF` force-clear cutoff.
|
|
375
|
+
- `signingKey` - the cache-persisted Better Auth secret and
|
|
376
|
+
`TUNNEL_AUTH_SESSION_CUTOFF` force-clear cutoff.
|
|
386
377
|
- `allowlist` - email domain / glob / regex matching and `looksLikeEmail`.
|
|
387
378
|
- `headers` - the inbound-header allow-list: `toHeaderPolicy()`,
|
|
388
379
|
`DEFAULT_FORWARD_HEADERS`, and the `PROTECTED_HEADERS` no pattern can forward.
|
|
@@ -391,6 +382,6 @@ the selected release and executable path, then removes the temporary directory.
|
|
|
391
382
|
- `portr` - portr install, config rendering, and child launch.
|
|
392
383
|
- `env` - the environment-variable names, each with its deprecated aliases.
|
|
393
384
|
|
|
394
|
-
Browser-safe
|
|
395
|
-
|
|
396
|
-
|
|
385
|
+
Browser-safe gate contracts live in
|
|
386
|
+
[`@dbx-tools/shared-auth`](../../shared/auth); the passkey-first React login and
|
|
387
|
+
credential manager live in [`@dbx-tools/ui-auth`](../../ui/auth).
|
package/index.ts
CHANGED
|
@@ -2,28 +2,24 @@
|
|
|
2
2
|
// Regenerated from the exporting modules in ./src.
|
|
3
3
|
// Hand edits are overwritten on the next watch; this file is read-only.
|
|
4
4
|
|
|
5
|
+
export const PACKAGE_IDENTIFIER = "@dbx-tools/tunnel";
|
|
5
6
|
export * as allowlist from "./src/allowlist.ts";
|
|
6
7
|
export * as codeEmail from "./src/code-email.ts";
|
|
7
8
|
export * as gate from "./src/gate.ts";
|
|
8
9
|
export * as headers from "./src/headers.ts";
|
|
9
10
|
export * as interceptor from "./src/interceptor.ts";
|
|
10
|
-
export * as otp from "./src/otp.ts";
|
|
11
11
|
export * as plugin from "./src/plugin.ts";
|
|
12
12
|
export * as portr from "./src/portr.ts";
|
|
13
|
-
export * as rateLimit from "./src/rate-limit.ts";
|
|
14
13
|
export * as sendCode from "./src/send-code.ts";
|
|
15
14
|
export * as signingKey from "./src/signing-key.ts";
|
|
16
15
|
export type { CodeCopy } from "./src/code-email.ts";
|
|
17
|
-
export { AUTH_PREFIX, UNAUTHORIZED_BODY
|
|
16
|
+
export { AUTH_PREFIX, UNAUTHORIZED_BODY } from "./src/gate.ts";
|
|
18
17
|
export type { GateOptions, GateAction } from "./src/gate.ts";
|
|
19
18
|
export { PROTECTED_HEADERS, DEFAULT_FORWARD_HEADERS } from "./src/headers.ts";
|
|
20
19
|
export type { HeaderPolicy } from "./src/headers.ts";
|
|
21
20
|
export type { TunnelInterceptorOptions } from "./src/interceptor.ts";
|
|
22
|
-
export { CodeStore } from "./src/otp.ts";
|
|
23
|
-
export type { VerifyOutcome } from "./src/otp.ts";
|
|
24
21
|
export { AuthGatePlugin, authGate } from "./src/plugin.ts";
|
|
25
22
|
export type { AuthGateConfig, SendCodeOptions, ResolvedAuthGateConfig, AuthGateApi } from "./src/plugin.ts";
|
|
26
23
|
export type { PortrInstallOptions, PortrConfig } from "./src/portr.ts";
|
|
27
|
-
export { RateLimiter } from "./src/rate-limit.ts";
|
|
28
24
|
export { KEY_TTL_SECONDS } from "./src/signing-key.ts";
|
|
29
25
|
export type { SigningKey } from "./src/signing-key.ts";
|
package/lib/index.d.ts
CHANGED
|
@@ -1,25 +1,21 @@
|
|
|
1
|
+
export declare const PACKAGE_IDENTIFIER = "@dbx-tools/tunnel";
|
|
1
2
|
export * as allowlist from "./src/allowlist.ts";
|
|
2
3
|
export * as codeEmail from "./src/code-email.ts";
|
|
3
4
|
export * as gate from "./src/gate.ts";
|
|
4
5
|
export * as headers from "./src/headers.ts";
|
|
5
6
|
export * as interceptor from "./src/interceptor.ts";
|
|
6
|
-
export * as otp from "./src/otp.ts";
|
|
7
7
|
export * as plugin from "./src/plugin.ts";
|
|
8
8
|
export * as portr from "./src/portr.ts";
|
|
9
|
-
export * as rateLimit from "./src/rate-limit.ts";
|
|
10
9
|
export * as sendCode from "./src/send-code.ts";
|
|
11
10
|
export * as signingKey from "./src/signing-key.ts";
|
|
12
11
|
export type { CodeCopy } from "./src/code-email.ts";
|
|
13
|
-
export { AUTH_PREFIX, UNAUTHORIZED_BODY
|
|
12
|
+
export { AUTH_PREFIX, UNAUTHORIZED_BODY } from "./src/gate.ts";
|
|
14
13
|
export type { GateOptions, GateAction } from "./src/gate.ts";
|
|
15
14
|
export { PROTECTED_HEADERS, DEFAULT_FORWARD_HEADERS } from "./src/headers.ts";
|
|
16
15
|
export type { HeaderPolicy } from "./src/headers.ts";
|
|
17
16
|
export type { TunnelInterceptorOptions } from "./src/interceptor.ts";
|
|
18
|
-
export { CodeStore } from "./src/otp.ts";
|
|
19
|
-
export type { VerifyOutcome } from "./src/otp.ts";
|
|
20
17
|
export { AuthGatePlugin, authGate } from "./src/plugin.ts";
|
|
21
18
|
export type { AuthGateConfig, SendCodeOptions, ResolvedAuthGateConfig, AuthGateApi } from "./src/plugin.ts";
|
|
22
19
|
export type { PortrInstallOptions, PortrConfig } from "./src/portr.ts";
|
|
23
|
-
export { RateLimiter } from "./src/rate-limit.ts";
|
|
24
20
|
export { KEY_TTL_SECONDS } from "./src/signing-key.ts";
|
|
25
21
|
export type { SigningKey } from "./src/signing-key.ts";
|
package/lib/index.js
CHANGED
|
@@ -1,21 +1,18 @@
|
|
|
1
1
|
// GENERATED by projen watch - DO NOT EDIT.
|
|
2
2
|
// Regenerated from the exporting modules in ./src.
|
|
3
3
|
// Hand edits are overwritten on the next watch; this file is read-only.
|
|
4
|
+
export const PACKAGE_IDENTIFIER = "@dbx-tools/tunnel";
|
|
4
5
|
export * as allowlist from "./src/allowlist.js";
|
|
5
6
|
export * as codeEmail from "./src/code-email.js";
|
|
6
7
|
export * as gate from "./src/gate.js";
|
|
7
8
|
export * as headers from "./src/headers.js";
|
|
8
9
|
export * as interceptor from "./src/interceptor.js";
|
|
9
|
-
export * as otp from "./src/otp.js";
|
|
10
10
|
export * as plugin from "./src/plugin.js";
|
|
11
11
|
export * as portr from "./src/portr.js";
|
|
12
|
-
export * as rateLimit from "./src/rate-limit.js";
|
|
13
12
|
export * as sendCode from "./src/send-code.js";
|
|
14
13
|
export * as signingKey from "./src/signing-key.js";
|
|
15
|
-
export { AUTH_PREFIX, UNAUTHORIZED_BODY
|
|
14
|
+
export { AUTH_PREFIX, UNAUTHORIZED_BODY } from "./src/gate.js";
|
|
16
15
|
export { PROTECTED_HEADERS, DEFAULT_FORWARD_HEADERS } from "./src/headers.js";
|
|
17
|
-
export { CodeStore } from "./src/otp.js";
|
|
18
16
|
export { AuthGatePlugin, authGate } from "./src/plugin.js";
|
|
19
|
-
export { RateLimiter } from "./src/rate-limit.js";
|
|
20
17
|
export { KEY_TTL_SECONDS } from "./src/signing-key.js";
|
|
21
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
18
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFDM0MsbURBQW1EO0FBQ25ELHdFQUF3RTtBQUV4RSxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRyxtQkFBbUIsQ0FBQztBQUN0RCxPQUFPLEtBQUssU0FBUyxNQUFNLG9CQUFvQixDQUFDO0FBQ2hELE9BQU8sS0FBSyxTQUFTLE1BQU0scUJBQXFCLENBQUM7QUFDakQsT0FBTyxLQUFLLElBQUksTUFBTSxlQUFlLENBQUM7QUFDdEMsT0FBTyxLQUFLLE9BQU8sTUFBTSxrQkFBa0IsQ0FBQztBQUM1QyxPQUFPLEtBQUssV0FBVyxNQUFNLHNCQUFzQixDQUFDO0FBQ3BELE9BQU8sS0FBSyxNQUFNLE1BQU0saUJBQWlCLENBQUM7QUFDMUMsT0FBTyxLQUFLLEtBQUssTUFBTSxnQkFBZ0IsQ0FBQztBQUN4QyxPQUFPLEtBQUssUUFBUSxNQUFNLG9CQUFvQixDQUFDO0FBQy9DLE9BQU8sS0FBSyxVQUFVLE1BQU0sc0JBQXNCLENBQUM7QUFFbkQsT0FBTyxFQUFFLFdBQVcsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUUvRCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUc5RSxPQUFPLEVBQUUsY0FBYyxFQUFFLFFBQVEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRzNELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEdFTkVSQVRFRCBieSBwcm9qZW4gd2F0Y2ggLSBETyBOT1QgRURJVC5cbi8vIFJlZ2VuZXJhdGVkIGZyb20gdGhlIGV4cG9ydGluZyBtb2R1bGVzIGluIC4vc3JjLlxuLy8gSGFuZCBlZGl0cyBhcmUgb3ZlcndyaXR0ZW4gb24gdGhlIG5leHQgd2F0Y2g7IHRoaXMgZmlsZSBpcyByZWFkLW9ubHkuXG5cbmV4cG9ydCBjb25zdCBQQUNLQUdFX0lERU5USUZJRVIgPSBcIkBkYngtdG9vbHMvdHVubmVsXCI7XG5leHBvcnQgKiBhcyBhbGxvd2xpc3QgZnJvbSBcIi4vc3JjL2FsbG93bGlzdC50c1wiO1xuZXhwb3J0ICogYXMgY29kZUVtYWlsIGZyb20gXCIuL3NyYy9jb2RlLWVtYWlsLnRzXCI7XG5leHBvcnQgKiBhcyBnYXRlIGZyb20gXCIuL3NyYy9nYXRlLnRzXCI7XG5leHBvcnQgKiBhcyBoZWFkZXJzIGZyb20gXCIuL3NyYy9oZWFkZXJzLnRzXCI7XG5leHBvcnQgKiBhcyBpbnRlcmNlcHRvciBmcm9tIFwiLi9zcmMvaW50ZXJjZXB0b3IudHNcIjtcbmV4cG9ydCAqIGFzIHBsdWdpbiBmcm9tIFwiLi9zcmMvcGx1Z2luLnRzXCI7XG5leHBvcnQgKiBhcyBwb3J0ciBmcm9tIFwiLi9zcmMvcG9ydHIudHNcIjtcbmV4cG9ydCAqIGFzIHNlbmRDb2RlIGZyb20gXCIuL3NyYy9zZW5kLWNvZGUudHNcIjtcbmV4cG9ydCAqIGFzIHNpZ25pbmdLZXkgZnJvbSBcIi4vc3JjL3NpZ25pbmcta2V5LnRzXCI7XG5leHBvcnQgdHlwZSB7IENvZGVDb3B5IH0gZnJvbSBcIi4vc3JjL2NvZGUtZW1haWwudHNcIjtcbmV4cG9ydCB7IEFVVEhfUFJFRklYLCBVTkFVVEhPUklaRURfQk9EWSB9IGZyb20gXCIuL3NyYy9nYXRlLnRzXCI7XG5leHBvcnQgdHlwZSB7IEdhdGVPcHRpb25zLCBHYXRlQWN0aW9uIH0gZnJvbSBcIi4vc3JjL2dhdGUudHNcIjtcbmV4cG9ydCB7IFBST1RFQ1RFRF9IRUFERVJTLCBERUZBVUxUX0ZPUldBUkRfSEVBREVSUyB9IGZyb20gXCIuL3NyYy9oZWFkZXJzLnRzXCI7XG5leHBvcnQgdHlwZSB7IEhlYWRlclBvbGljeSB9IGZyb20gXCIuL3NyYy9oZWFkZXJzLnRzXCI7XG5leHBvcnQgdHlwZSB7IFR1bm5lbEludGVyY2VwdG9yT3B0aW9ucyB9IGZyb20gXCIuL3NyYy9pbnRlcmNlcHRvci50c1wiO1xuZXhwb3J0IHsgQXV0aEdhdGVQbHVnaW4sIGF1dGhHYXRlIH0gZnJvbSBcIi4vc3JjL3BsdWdpbi50c1wiO1xuZXhwb3J0IHR5cGUgeyBBdXRoR2F0ZUNvbmZpZywgU2VuZENvZGVPcHRpb25zLCBSZXNvbHZlZEF1dGhHYXRlQ29uZmlnLCBBdXRoR2F0ZUFwaSB9IGZyb20gXCIuL3NyYy9wbHVnaW4udHNcIjtcbmV4cG9ydCB0eXBlIHsgUG9ydHJJbnN0YWxsT3B0aW9ucywgUG9ydHJDb25maWcgfSBmcm9tIFwiLi9zcmMvcG9ydHIudHNcIjtcbmV4cG9ydCB7IEtFWV9UVExfU0VDT05EUyB9IGZyb20gXCIuL3NyYy9zaWduaW5nLWtleS50c1wiO1xuZXhwb3J0IHR5cGUgeyBTaWduaW5nS2V5IH0gZnJvbSBcIi4vc3JjL3NpZ25pbmcta2V5LnRzXCI7XG4iXX0=
|
package/lib/src/allowlist.d.ts
CHANGED
package/lib/src/allowlist.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Unified
|
|
2
|
+
* Unified identity authorization matching for the passwordless gate.
|
|
3
3
|
*
|
|
4
4
|
* Each pattern in the configured list is one of three shapes:
|
|
5
5
|
*
|
|
@@ -54,4 +54,4 @@ export function matchesAllowlist(email, patterns) {
|
|
|
54
54
|
export function looksLikeEmail(value) {
|
|
55
55
|
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value.trim());
|
|
56
56
|
}
|
|
57
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
57
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWxsb3dsaXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2FsbG93bGlzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBd0JHO0FBRUgsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBRWpELCtEQUErRDtBQUMvRCxTQUFTLGNBQWMsQ0FBQyxLQUFhLEVBQUUsS0FBYTtJQUNsRCxNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDN0IsSUFBSSxDQUFDLE9BQU87UUFBRSxPQUFPLEtBQUssQ0FBQztJQUMzQixNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUM7SUFFM0MsOEVBQThFO0lBQzlFLDJFQUEyRTtJQUMzRSx3RUFBd0U7SUFDeEUsMkNBQTJDO0lBQzNDLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUNqRixNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUN2RCxNQUFNLEVBQUUsR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3BDLE9BQU8sRUFBRSxJQUFJLENBQUMsSUFBSSxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUMsS0FBSyxNQUFNLENBQUM7SUFDckQsQ0FBQztJQUVELE9BQU8sT0FBTyxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEtBQUssQ0FBQztBQUN4RCxDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsTUFBTSxVQUFVLGdCQUFnQixDQUFDLEtBQWEsRUFBRSxRQUF1QztJQUNyRixJQUFJLENBQUMsS0FBSyxJQUFJLENBQUMsUUFBUSxJQUFJLFFBQVEsQ0FBQyxNQUFNLEtBQUssQ0FBQztRQUFFLE9BQU8sS0FBSyxDQUFDO0lBQy9ELE9BQU8sUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsY0FBYyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO0FBQ2hFLENBQUM7QUFFRCxrRkFBa0Y7QUFDbEYsTUFBTSxVQUFVLGNBQWMsQ0FBQyxLQUFhO0lBQzFDLE9BQU8sNEJBQTRCLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO0FBQ3pELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFVuaWZpZWQgaWRlbnRpdHkgYXV0aG9yaXphdGlvbiBtYXRjaGluZyBmb3IgdGhlIHBhc3N3b3JkbGVzcyBnYXRlLlxuICpcbiAqIEVhY2ggcGF0dGVybiBpbiB0aGUgY29uZmlndXJlZCBsaXN0IGlzIG9uZSBvZiB0aHJlZSBzaGFwZXM6XG4gKlxuICogICAtICoqZG9tYWluIHNob3J0Y3V0KiogLSBgZXhhbXBsZS5jb21gIG9yIGBAZXhhbXBsZS5jb21gOiBtYXRjaGVzIGFueVxuICogICAgIGFkZHJlc3Mgd2hvc2UgZG9tYWluIGVxdWFscyBpdC4gVGhpcyBpcyB0aGUgZ2F0ZSdzIE9XTiBzZW1hbnRpYyAoYSBiYXJlXG4gKiAgICAgdmFsdWUgbWVhbnMgXCJ0aGUgZG9tYWluXCIsIG5vdCBcInRoZSB3aG9sZSBhZGRyZXNzXCIpLCBzbyBpdCBpcyBoYW5kbGVkIGhlcmUuXG4gKiAgIC0gKipnbG9iKiogLSBjb250YWlucyBgKmAgb3IgYD9gLCBlLmcuIGAqQGV4YW1wbGUuY29tYDogbWF0Y2hlZCBhZ2FpbnN0IHRoZVxuICogICAgIFdIT0xFIGFkZHJlc3Mgd2l0aCBzaGVsbC1zdHlsZSB3aWxkY2FyZHMuXG4gKiAgIC0gKipyZWdleCoqIC0gd3JhcHBlZCBpbiBzbGFzaGVzLCBgLy4uLi8gW2ZsYWdzXWA6IHRlc3RlZCBhZ2FpbnN0IHRoZSB3aG9sZVxuICogICAgIGFkZHJlc3MuIEFuIGludmFsaWQgcmVnZXggbmV2ZXIgbWF0Y2hlcyAoaXQgaXMgc2tpcHBlZCB3aXRoIGEgd2FybmluZ1xuICogICAgIHJhdGhlciB0aGFuIHRocm93aW5nKS5cbiAqXG4gKiBPbmx5IHRoZSBmaXJzdCBzaGFwZSBpcyB0aGlzIG1vZHVsZSdzIGJ1c2luZXNzOiB0aGUgZ2xvYiBhbmQgcmVnZXggc2hhcGVzIGFyZVxuICogZGVsZWdhdGVkIHRvIGBAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlYCdzIHtAbGluayBwYXR0ZXJuLnRvUGF0dGVybn0sIHdoaWNoIGlzXG4gKiB3aGVyZSB0aGF0IGNvbXBpbGF0aW9uIGxpdmVzIGZvciBldmVyeSBhbGxvdy1saXN0IGluIHRoZSByZXBvICh0aGUgdHVubmVsJ3NcbiAqIGluYm91bmQtaGVhZGVyIHBvbGljeSB1c2VzIHRoZSBzYW1lIG9uZSkuIE1hdGNoaW5nIGlzIGNhc2UtaW5zZW5zaXRpdmVcbiAqIHRocm91Z2hvdXQuXG4gKlxuICogQW4gRU1QVFkgbGlzdCBtYXRjaGVzIG5vYm9keSAoZmFpbCBjbG9zZWQpOiBhbiBhcHAgdGhhdCBlbmFibGVzIHRoZSBnYXRlIGJ1dFxuICogY29uZmlndXJlcyBubyBwYXR0ZXJucyBsZXRzIG5vIG9uZSBpbiwgd2hpY2ggaXMgdGhlIHNhZmUgZGVmYXVsdC5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cblxuaW1wb3J0IHsgcGF0dGVybiB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlXCI7XG5cbi8qKiBUcnVlIHdoZW4gYGVtYWlsYCBtYXRjaGVzIGEgc2luZ2xlIGFsbG93LWxpc3QgYHBhdHRlcm5gLiAqL1xuZnVuY3Rpb24gbWF0Y2hlc1BhdHRlcm4oZW1haWw6IHN0cmluZywgZW50cnk6IHN0cmluZyk6IGJvb2xlYW4ge1xuICBjb25zdCB0cmltbWVkID0gZW50cnkudHJpbSgpO1xuICBpZiAoIXRyaW1tZWQpIHJldHVybiBmYWxzZTtcbiAgY29uc3QgYWRkcmVzcyA9IGVtYWlsLnRyaW0oKS50b0xvd2VyQ2FzZSgpO1xuXG4gIC8vIEEgYmFyZSB2YWx1ZSB3aXRoIG5vIHdpbGRjYXJkIGFuZCBubyByZWdleCBkZWxpbWl0ZXJzIGlzIGEgRE9NQUlOIHNob3J0Y3V0LFxuICAvLyB0aGUgb25lIHNoYXBlIHNoYXJlZC1jb3JlIGNhbm5vdCBpbmZlcjogdGhlcmUgaXQgd291bGQgbWVhbiB3aG9sZS1zdHJpbmdcbiAgLy8gZXF1YWxpdHkgYWdhaW5zdCB0aGUgYWRkcmVzcywgd2hpY2ggaXMgbmV2ZXIgd2hhdCBhbiBvcGVyYXRvciB3cml0aW5nXG4gIC8vIGBleGFtcGxlLmNvbWAgaW4gYW4gYWNjZXNzIGxpc3QgaW50ZW5kcy5cbiAgaWYgKCF0cmltbWVkLnN0YXJ0c1dpdGgoXCIvXCIpICYmICF0cmltbWVkLmluY2x1ZGVzKFwiKlwiKSAmJiAhdHJpbW1lZC5pbmNsdWRlcyhcIj9cIikpIHtcbiAgICBjb25zdCBkb21haW4gPSB0cmltbWVkLnJlcGxhY2UoL15ALywgXCJcIikudG9Mb3dlckNhc2UoKTtcbiAgICBjb25zdCBhdCA9IGFkZHJlc3MubGFzdEluZGV4T2YoXCJAXCIpO1xuICAgIHJldHVybiBhdCA+PSAwICYmIGFkZHJlc3Muc2xpY2UoYXQgKyAxKSA9PT0gZG9tYWluO1xuICB9XG5cbiAgcmV0dXJuIHBhdHRlcm4udG9QYXR0ZXJuKHRyaW1tZWQpPy4oYWRkcmVzcykgPz8gZmFsc2U7XG59XG5cbi8qKlxuICogVHJ1ZSB3aGVuIGBlbWFpbGAgaXMgYWxsb3dlZCBieSBBTlkgcGF0dGVybiBpbiBgcGF0dGVybnNgLiBBbiBlbXB0eSAob3JcbiAqIG1pc3NpbmcpIGxpc3QgYWxsb3dzIG5vYm9keSAtIHRoZSBnYXRlIGZhaWxzIGNsb3NlZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1hdGNoZXNBbGxvd2xpc3QoZW1haWw6IHN0cmluZywgcGF0dGVybnM6IHJlYWRvbmx5IHN0cmluZ1tdIHwgdW5kZWZpbmVkKTogYm9vbGVhbiB7XG4gIGlmICghZW1haWwgfHwgIXBhdHRlcm5zIHx8IHBhdHRlcm5zLmxlbmd0aCA9PT0gMCkgcmV0dXJuIGZhbHNlO1xuICByZXR1cm4gcGF0dGVybnMuc29tZSgoZW50cnkpID0+IG1hdGNoZXNQYXR0ZXJuKGVtYWlsLCBlbnRyeSkpO1xufVxuXG4vKiogUm91Z2ggc2hhcGUgY2hlY2sgc28gYSBjbGVhcmx5LWludmFsaWQgYWRkcmVzcyBpcyByZWplY3RlZCBiZWZvcmUgYW55IHdvcmsuICovXG5leHBvcnQgZnVuY3Rpb24gbG9va3NMaWtlRW1haWwodmFsdWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICByZXR1cm4gL15bXlxcc0BdK0BbXlxcc0BdK1xcLlteXFxzQF0rJC8udGVzdCh2YWx1ZS50cmltKCkpO1xufVxuIl19
|
package/lib/src/gate.d.ts
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
* nothing to forward to. It either short-circuits (401, or answers the open login
|
|
7
7
|
* routes) or calls `next()` to let the app's real handlers run. It is the
|
|
8
8
|
* "stands in for AppKit auth" path:
|
|
9
|
-
* a portr caller
|
|
10
|
-
*
|
|
9
|
+
* a portr caller authenticates with Better Auth OTP or a passkey, and on
|
|
10
|
+
* success the gate injects the identity headers AppKit reads.
|
|
11
11
|
*
|
|
12
12
|
* WHICH TRAFFIC IS GATED - the `Host` header, not the socket. portr's client
|
|
13
13
|
* forwards with Go's `httputil.NewSingleHostReverseProxy` and a `Director` that
|
|
@@ -22,10 +22,13 @@
|
|
|
22
22
|
* @module
|
|
23
23
|
*/
|
|
24
24
|
import type { IncomingMessage } from "node:http";
|
|
25
|
-
import type { RequestHandler } from "express";
|
|
25
|
+
import type { RequestHandler, Response } from "express";
|
|
26
26
|
import { type HeaderPolicy } from "./headers.ts";
|
|
27
27
|
import type { AuthGateApi } from "./plugin.ts";
|
|
28
|
-
|
|
28
|
+
type WebRequestInput = IncomingMessage & {
|
|
29
|
+
body?: unknown;
|
|
30
|
+
originalUrl?: string;
|
|
31
|
+
};
|
|
29
32
|
export declare const AUTH_PREFIX = "/api/email/auth";
|
|
30
33
|
/** Options for {@link mountGate}. */
|
|
31
34
|
export interface GateOptions {
|
|
@@ -57,6 +60,9 @@ export declare function isTunnelHost(req: IncomingMessage, publicDomain: string
|
|
|
57
60
|
* varying the header. Called before {@link stripHeaders}.
|
|
58
61
|
*/
|
|
59
62
|
export declare function clientIp(req: IncomingMessage): string;
|
|
63
|
+
export declare function webHeaders(req: IncomingMessage): Headers;
|
|
64
|
+
export declare function webRequest(req: WebRequestInput): Promise<globalThis.Request>;
|
|
65
|
+
export declare function sendWebResponse(res: Response, response: globalThis.Response): Promise<void>;
|
|
60
66
|
/**
|
|
61
67
|
* What the caller should do with a request, from {@link gateRequest}.
|
|
62
68
|
*
|
|
@@ -91,10 +97,6 @@ export declare const UNAUTHORIZED_BODY: {
|
|
|
91
97
|
readonly error: "authentication required";
|
|
92
98
|
readonly loginPath: "/api/email/auth";
|
|
93
99
|
};
|
|
94
|
-
/** The `Set-Cookie` value that issues a verified session. */
|
|
95
|
-
export declare function sessionSetCookie(sessionToken: string, maxAgeSeconds: number): string;
|
|
96
|
-
/** The `Set-Cookie` value that clears the session. */
|
|
97
|
-
export declare const LOGOUT_SET_COOKIE = "dbx-tools-auth=; Path=/; HttpOnly; Max-Age=0";
|
|
98
100
|
/**
|
|
99
101
|
* Register the login routes and the gating middleware on the app's Express
|
|
100
102
|
* instance. Called from {@link AuthGatePlugin} with the router AppKit hands
|
|
@@ -104,4 +106,5 @@ export declare const LOGOUT_SET_COOKIE = "dbx-tools-auth=; Path=/; HttpOnly; Max
|
|
|
104
106
|
* routes live at an ABSOLUTE path (`/api/email/auth/*`, the client's contract),
|
|
105
107
|
* not under the plugin's `/api/authGate` base.
|
|
106
108
|
*/
|
|
107
|
-
export declare function mountGate(opts: GateOptions,
|
|
109
|
+
export declare function mountGate(opts: GateOptions, _addRoute: (method: "get" | "post", path: string, handler: RequestHandler) => void, addMiddleware: (path: string, handler: RequestHandler) => void): void;
|
|
110
|
+
export {};
|