MCPcopy Create free account
hub / github.com/UsefulSoftwareCo/executor / makeAuthOptions

Function makeAuthOptions

apps/host-selfhost/src/auth/better-auth.ts:64–209  ·  view source on GitHub ↗
(client: Client, getOrganizationId: () => string, gate?: SignupGate)

Source from the content-addressed store, hash-verified

62// ---------------------------------------------------------------------------
63
64const makeAuthOptions = (client: Client, getOrganizationId: () => string, gate?: SignupGate) => {
65 const config = loadConfig();
66 // Always resolved (generated + persisted when no env is set); this guards only
67 // an explicitly-set env secret that is too weak.
68 const secret = config.authSecret;
69 if (secret.length < 32) {
70 // oxlint-disable-next-line executor/no-try-catch-or-throw, executor/no-error-constructor -- boundary: a multi-user auth server must not boot with a weak session secret
71 throw new Error("BETTER_AUTH_SECRET (or AUTH_SECRET), if set, must be at least 32 characters");
72 }
73 return {
74 // Hand Better Auth the SAME libSQL client SelfHostDb already opened — NOT a
75 // fresh `{ url }` connection. `{ client }` makes LibsqlDialect adopt the
76 // existing handle (closeClient=false, so SelfHostDb keeps ownership). One
77 // connection means one WAL: see the header comment for why a second
78 // connection is the self-host data-loss bug.
79 //
80 // The cast bridges a dependency skew: @libsql/kysely-libsql pins an older
81 // @libsql/core (0.8) than @libsql/client (0.17), so the two `Client` types
82 // differ — only in `.sync()` (embedded-replica replication, unused here).
83 // The dialect calls execute/batch/transaction/close, which are identical
84 // across both versions, so sharing the 0.17 client is sound at runtime.
85 database: {
86 // oxlint-disable-next-line executor/no-double-cast -- boundary: the two @libsql/core versions' Client types are structurally identical for the calls the dialect makes (see above); no schema/decode applies to a native client handle.
87 dialect: new LibsqlDialect({ client } as unknown as LibsqlDialectConfig),
88 type: "sqlite" as const,
89 },
90 secret,
91 // The browser Origin must match this exactly; CLI/MCP bearer requests carry
92 // no Origin and are unaffected. `config.webBaseUrl` resolves from an explicit
93 // EXECUTOR_WEB_BASE_URL, else a platform-injected origin (Railway/Render/Fly/
94 // …), else localhost — so a PaaS deploy is zero-config and any other host
95 // sets the one variable (a loud warning fires on the localhost fallback).
96 // See config.ts. We deliberately do NOT derive this from the request `Host`:
97 // matching the ecosystem (Windmill `BASE_URL`, n8n `WEBHOOK_URL`), a pinned
98 // origin keeps host-header injection out of OAuth redirects and links.
99 baseURL: config.webBaseUrl,
100 trustedOrigins: [config.webBaseUrl],
101 emailAndPassword: { enabled: true },
102 // `apiKey` issues long-lived personal keys (the API-keys page). With
103 // `enableSessionForAPIKeys`, presenting a key resolves to its owner's
104 // session — so a key works as a Bearer token for the API + MCP endpoint.
105 //
106 // `mcp()` adds the MCP OAuth Authorization Server: dynamic client
107 // registration + authorize + token under /api/auth/mcp/*, the discovery
108 // docs, and `getMcpSession` (opaque-bearer validation). It WRAPS
109 // oidcProvider — do NOT also add oidcProvider. The two root well-known docs
110 // are re-emitted by the shared envelope (MCP clients probe the origin root,
111 // not the /api/auth basePath).
112 plugins: [
113 organization(),
114 admin(),
115 apiKey({ enableSessionForAPIKeys: true, rateLimit: { enabled: false } }),
116 bearer(),
117 // RFC 8628 device authorization, the CLI `executor login` flow. Registers
118 // /device/code + /device/token + the approval endpoints; the issued token
119 // is an opaque session that `bearer()` (above) accepts as `Authorization:
120 // Bearer` on the /api/* plane. `validateClient` is left unset, so any
121 // client_id is accepted (the CLI presents "executor-cli"). `verificationUri`

Callers 1

createAuthInstanceFunction · 0.85

Calls 6

loadConfigFunction · 0.90
findRedeemableCodeFunction · 0.90
consumeInviteCodeFunction · 0.90
orgHasNoMembersFunction · 0.85
inviteCodeFromFunction · 0.85
mcpFunction · 0.50

Tested by

no test coverage detected