@wakeshift/sdk 0.2.0 → 0.3.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/dist/guest.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"guest.js","sourceRoot":"","sources":["../src/guest.ts"],"names":[],"mappings":"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","sourcesContent":["// GuestAuth signs MCP clients (Claude Code, Codex…) in to a headless app as\n// guests: no Wakeshift account, no account with the app. It's a small OAuth\n// server inside the app (dynamic client registration, authorize with PKCE,\n// tokens), and it keeps no state: clients, codes and tokens are signed with\n// a key derived from the app's key. A port of the Go SDK's appkit.GuestAuth.\n//\n// Each registered client (an install of a harness) is one guest: its own\n// workspace, with an agent named after the harness (claude-code). Sign-in\n// shows nothing: the person added the app to their agent, and that's the\n// consent.\n//\n// Since authorize has no user step, knowing a client_id must not be enough\n// to become its guest (client_ids travel in authorize URLs, which end up in\n// logs and browser history). Registration also gives the client a secret\n// (derived from the client_id, so nothing is stored), and the token\n// endpoint requires it with every code and refresh token. The guest's\n// workspace and agent are made at the code exchange, once the client has\n// authenticated, not at authorize.\n\nimport { createHash, createHmac, randomBytes, timingSafeEqual } from \"node:crypto\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\nimport { isIP } from \"node:net\";\nimport type { AuthInfo } from \"@modelcontextprotocol/sdk/server/auth/types.js\";\nimport { WakeshiftError } from \"./errors.js\";\nimport { harnessAgent } from \"./harness.js\";\nimport { RateLimiter, clientAddr } from \"./limits.js\";\nimport { seal, unseal } from \"./sealed.js\";\nimport type { Wakeshift } from \"./wakeshift.js\";\n\n/** Who a guest access token is for. */\nexport interface Guest {\n /**\n * The app's ID for the guest: pass it as wake.call's user, so topics keep\n * the guest's conversations in its workspace. guest:<id>, one per\n * registered client.\n */\n user: string;\n /** The guest's workspace and agent (named after its harness: claude-code). */\n workspace: string;\n agent: string;\n /** The client's name, e.g. \"Claude Code\". */\n client: string;\n expires: Date;\n}\n\nexport interface GuestAuthOptions {\n wake: Wakeshift;\n /** The app's MCP URL: the OAuth resource (https://…/mcp). */\n mcpUrl: string;\n /** The app's public URL, where the OAuth endpoints are (default: mcpUrl without /mcp). */\n base?: string;\n /** Seconds an access token lasts (default an hour). */\n accessTtl?: number;\n /** Seconds a refresh token lasts (default 30 days); each refresh returns a new one, good for this long from then. */\n refreshTtl?: number;\n /**\n * Asked at each refresh whether the guest's refresh token issued at\n * issuedAt is revoked: an app's own denylist, or a per-guest cutoff. A\n * refresh is also refused once wake.forgetUser(guest.user) has run (and,\n * with grants, once the guest's grant is revoked), so either signs the\n * guest out within accessTtl.\n */\n revoked?: (guest: Guest, issuedAt: Date) => boolean | Promise<boolean>;\n /**\n * Also give each guest's agent a grant for the app's manifest agent scope,\n * as the Go SDK does, and refuse refreshes once it's revoked. Needs a\n * manifest with an agent scope; topics don't use grants, so leave it off\n * for an app that only uses topics.\n */\n grants?: boolean;\n /**\n * How many trusted proxies in front append to X-Forwarded-For (behind\n * Google's load balancer: 2), for the per-address limits. 0 (the\n * default): the connection's own address.\n */\n proxyHops?: number;\n /** Registrations (default 20) and token requests (default 60) per address per rateWindow, per process; negative turns a limit off. */\n registerLimit?: number;\n tokenLimit?: number;\n /** Seconds (default 600). */\n rateWindow?: number;\n /** Called with a problem worth logging (never with a token or secret). Default: console.error. */\n onError?: (message: string, err: unknown) => void;\n /** For tests. */\n now?: () => number;\n}\n\n/** What the MCP transport passes to tool callbacks (extra.authInfo) for a guest. */\nexport type GuestAuthInfo = AuthInfo & { extra: { guest: Guest } };\n\n/** The guest a tool call came from, if GuestAuth signed it in (extra: the tool callback's second argument). */\nexport function guestOf(extra: { authInfo?: AuthInfo } | undefined): Guest | undefined {\n const g = extra?.authInfo?.extra?.guest as Guest | undefined;\n return g && typeof g.user === \"string\" ? g : undefined;\n}\n\n// How long an authorization code is good for, in seconds.\nconst CODE_TTL = 60;\n// A PKCE code verifier, or an S256 challenge (RFC 7636 4.1, 4.2).\nconst PKCE_RE = /^[A-Za-z0-9._~-]{43,128}$/;\n\ninterface GuestClient {\n n: string; // name\n r: string[]; // redirect URIs\n x: string; // makes each registration its own guest (128 bits)\n}\n\ninterface GuestCode {\n c: string; // client_id\n r: string; // redirect URI\n s: string; // state\n p: string; // PKCE challenge\n e: number; // expires (unix seconds)\n k: true;\n}\n\ninterface GuestToken {\n w: string; // workspace\n a: string; // agent\n c: string; // client name\n u: string; // the app's user ID for the guest\n i?: string; // client_id (refresh tokens)\n t?: number; // issued at (refresh tokens)\n n?: string; // nonce: each refresh token its own\n e: number; // expires\n}\n\nclass OAuthFailure extends Error {\n constructor(\n readonly status: number,\n readonly code: string,\n message: string,\n ) {\n super(message);\n }\n}\n\nexport class GuestAuth {\n private readonly wake: Wakeshift;\n readonly mcpUrl: string;\n readonly base: string;\n private readonly accessTtl: number;\n private readonly refreshTtl: number;\n private readonly revokedFn?: GuestAuthOptions[\"revoked\"];\n private readonly grants: boolean;\n private readonly proxyHops: number;\n private readonly registers: RateLimiter;\n private readonly tokens: RateLimiter;\n private readonly errorFn: (message: string, err: unknown) => void;\n private readonly now: () => number;\n private readonly seed: Buffer;\n\n constructor(o: GuestAuthOptions) {\n if (!o?.wake) throw new Error(\"wakeshift: GuestAuth needs { wake }\");\n if (!o.mcpUrl) throw new Error(\"wakeshift: GuestAuth needs { mcpUrl }, the app's MCP URL\");\n this.wake = o.wake;\n this.mcpUrl = o.mcpUrl;\n this.base = (o.base ?? o.mcpUrl.replace(/\\/mcp$/, \"\")).replace(/\\/+$/, \"\");\n this.accessTtl = o.accessTtl && o.accessTtl > 0 ? o.accessTtl : 3600;\n this.refreshTtl = o.refreshTtl && o.refreshTtl > 0 ? o.refreshTtl : 30 * 24 * 3600;\n this.revokedFn = o.revoked;\n this.grants = !!o.grants;\n this.proxyHops = o.proxyHops ?? 0;\n this.now = o.now ?? Date.now;\n const window = (o.rateWindow && o.rateWindow > 0 ? o.rateWindow : 600) * 1000;\n this.registers = new RateLimiter(o.registerLimit === undefined || o.registerLimit === 0 ? 20 : o.registerLimit, window);\n this.tokens = new RateLimiter(o.tokenLimit === undefined || o.tokenLimit === 0 ? 60 : o.tokenLimit, window);\n this.errorFn = o.onError ?? ((m, err) => console.error(m, err instanceof WakeshiftError ? `${err.status} ${err.code}` : err));\n this.seed = this.wake.secretSeed();\n }\n\n /** Where MCP clients read the app's protected-resource metadata (RFC 9728). */\n get resourceMetadataUrl(): string {\n const u = new URL(this.mcpUrl);\n return u.origin + \"/.well-known/oauth-protected-resource\";\n }\n\n /**\n * Serves the OAuth endpoints and the metadata that points MCP clients at\n * them. Returns false for any other request, for your own routes. Mount it\n * before any body parser (it reads its own bodies), or after one: a parsed\n * req.body is used as it is.\n */\n async handle(req: IncomingMessage, res: ServerResponse): Promise<boolean> {\n const path = (req.url ?? \"/\").split(\"?\")[0];\n const routes: Record<string, [string, () => Promise<void> | void]> = {\n \"/.well-known/oauth-protected-resource\": [\"GET\", () => this.resourceMetadata(res)],\n \"/.well-known/oauth-protected-resource/mcp\": [\"GET\", () => this.resourceMetadata(res)],\n \"/.well-known/oauth-authorization-server\": [\"GET\", () => this.metadata(res)],\n \"/oauth/register\": [\"POST\", () => this.register(req, res)],\n \"/oauth/authorize\": [\"GET\", () => this.authorize(req, res)],\n \"/oauth/token\": [\"POST\", () => this.token(req, res)],\n };\n const r = routes[path];\n if (!r) return false;\n const method = req.method === \"HEAD\" ? \"GET\" : req.method;\n if (method !== r[0]) {\n res.writeHead(405, { Allow: r[0] === \"GET\" ? \"GET, HEAD\" : r[0], \"Content-Type\": \"text/plain\" });\n res.end(\"method not allowed\");\n return true;\n }\n try {\n await r[1]();\n } catch (err) {\n if (err instanceof OAuthFailure) {\n oauthErr(res, err.status, err.code, err.message);\n } else {\n this.errorFn(\"wakeshift: guest sign-in failed\", err);\n if (!res.headersSent) oauthErr(res, 500, \"server_error\", \"try again\");\n }\n }\n return true;\n }\n\n /**\n * Checks the request's bearer token. On success it returns the guest and\n * sets req.auth, which the MCP SDK's Streamable HTTP transport passes to\n * tool callbacks as extra.authInfo (read it with guestOf). On failure it\n * answers 401 with the WWW-Authenticate header MCP clients start signing\n * in from, and returns null.\n */\n authenticate(req: IncomingMessage & { auth?: AuthInfo }, res: ServerResponse): Guest | null {\n const h = req.headers.authorization ?? \"\";\n const m = /^Bearer\\s+(\\S+)$/i.exec(h);\n const g = m ? this.verify(m[1]) : null;\n if (!g) {\n res.writeHead(401, {\n \"WWW-Authenticate\": `Bearer resource_metadata=\"${this.resourceMetadataUrl}\"${m ? ', error=\"invalid_token\"' : \"\"}`,\n \"Content-Type\": \"text/plain\",\n });\n res.end(\"sign in: add this app to your agent again\");\n return null;\n }\n const info: GuestAuthInfo = {\n token: m![1],\n clientId: g.user,\n scopes: [],\n expiresAt: Math.floor(g.expires.getTime() / 1000),\n resource: new URL(this.mcpUrl),\n extra: { guest: g },\n };\n req.auth = info;\n return g;\n }\n\n /** Checks a guest access token; null if it isn't one of this app's, or has expired. */\n verify(token: string): Guest | null {\n const t = this.open<GuestToken>(\"access\", token);\n if (!t || typeof t.u !== \"string\" || typeof t.w !== \"string\" || typeof t.a !== \"string\" || typeof t.e !== \"number\" || this.seconds() > t.e) return null;\n return { user: t.u, workspace: t.w, agent: t.a, client: typeof t.c === \"string\" ? t.c : \"\", expires: new Date(t.e * 1000) };\n }\n\n private seconds(): number {\n return Math.floor(this.now() / 1000);\n }\n\n private resourceMetadata(res: ServerResponse): void {\n writeJSON(res, 200, { resource: this.mcpUrl, authorization_servers: [this.base], bearer_methods_supported: [\"header\"] });\n }\n\n private metadata(res: ServerResponse): void {\n const b = this.base;\n writeJSON(res, 200, {\n issuer: b,\n authorization_endpoint: b + \"/oauth/authorize\",\n token_endpoint: b + \"/oauth/token\",\n registration_endpoint: b + \"/oauth/register\",\n response_types_supported: [\"code\"],\n grant_types_supported: [\"authorization_code\", \"refresh_token\"],\n code_challenge_methods_supported: [\"S256\"],\n token_endpoint_auth_methods_supported: [\"client_secret_post\", \"client_secret_basic\"],\n });\n }\n\n // ── Signed values ──────────────────────────────────────────────────────\n // Each kind (client, code, access, refresh) is signed with its own key\n // derived from the app's key, so one can't pass for another.\n\n private mac(purpose: string): Buffer {\n return createHmac(\"sha256\", this.seed).update(\"appkit-guest:\" + purpose).digest();\n }\n\n private sign(purpose: string, v: unknown): string {\n return seal(this.mac(purpose), v);\n }\n\n private open<T>(purpose: string, s: unknown): T | null {\n return unseal<T>(this.mac(purpose), s);\n }\n\n /** The secret registration gave a client: an HMAC of its client_id, so it's never stored and only the app can make it. */\n private clientSecret(clientId: string): string {\n return createHmac(\"sha256\", this.mac(\"client-secret\")).update(clientId).digest(\"base64url\");\n }\n\n // clientAuth is the client a token request authenticated as, by HTTP\n // Basic (RFC 6749 2.3.1: each part form-encoded first) or client_id and\n // client_secret in the form, if its secret is right.\n private clientAuth(req: IncomingMessage, f: URLSearchParams): string | null {\n let id: string;\n let secret: string;\n const basic = /^Basic\\s+(\\S+)$/i.exec(req.headers.authorization ?? \"\");\n if (basic) {\n const raw = Buffer.from(basic[1], \"base64\").toString(\"utf8\");\n const colon = raw.indexOf(\":\");\n if (colon < 0) return null;\n const a = formUnescape(raw.slice(0, colon));\n const b = formUnescape(raw.slice(colon + 1));\n if (a === null || b === null || f.get(\"client_secret\")) return null; // one method at a time (RFC 6749 2.3)\n const formId = f.get(\"client_id\");\n if (formId && formId !== a) return null;\n id = a;\n secret = b;\n } else {\n id = f.get(\"client_id\") ?? \"\";\n secret = f.get(\"client_secret\") ?? \"\";\n }\n if (!id || !secret || !this.open<GuestClient>(\"client\", id)) return null;\n const want = Buffer.from(this.clientSecret(id));\n const got = Buffer.from(secret);\n if (got.length !== want.length || !timingSafeEqual(got, want)) return null;\n return id;\n }\n\n private async register(req: IncomingMessage, res: ServerResponse): Promise<void> {\n if (!this.registers.allow(clientAddr(req, this.proxyHops), this.now())) {\n throw new OAuthFailure(429, \"slow_down\", \"too many registrations from this address; try again later\");\n }\n let raw: unknown;\n try {\n raw = await readJSON(req, 16 << 10);\n } catch {\n throw new OAuthFailure(400, \"invalid_client_metadata\", \"redirect_uris is required\");\n }\n const inp = (raw ?? {}) as { client_name?: unknown; redirect_uris?: unknown };\n const uris = inp.redirect_uris;\n if (!Array.isArray(uris) || uris.length === 0 || uris.length > 5 || !uris.every((u) => typeof u === \"string\")) {\n throw new OAuthFailure(400, \"invalid_client_metadata\", \"redirect_uris is required\");\n }\n for (const u of uris as string[]) {\n if (u.length > 500 || !validRedirect(u)) throw new OAuthFailure(400, \"invalid_redirect_uri\", BAD_REDIRECT);\n }\n let name = typeof inp.client_name === \"string\" ? inp.client_name.trim() : \"\";\n if (!name || Buffer.byteLength(name) > 80) name = \"MCP client\";\n const id = this.sign(\"client\", { n: name, r: uris, x: randomBytes(16).toString(\"base64url\") } satisfies GuestClient);\n res.setHeader(\"Cache-Control\", \"no-store\");\n writeJSON(res, 201, {\n client_id: id,\n client_secret: this.clientSecret(id),\n client_secret_expires_at: 0,\n client_name: name,\n redirect_uris: uris,\n token_endpoint_auth_method: \"client_secret_post\",\n grant_types: [\"authorization_code\", \"refresh_token\"],\n response_types: [\"code\"],\n });\n }\n\n // authorize issues a code to a registered client with no user step (the\n // person added the app to their agent). It creates nothing: the guest is\n // made at the code exchange, once the client proves it holds its secret.\n private authorize(req: IncomingMessage, res: ServerResponse): void {\n const q = new URL(req.url ?? \"/\", \"http://x\").searchParams;\n const c = this.open<GuestClient>(\"client\", q.get(\"client_id\") ?? \"\");\n if (!c || !Array.isArray(c.r)) {\n textErr(res, 400, \"Unknown client. Register it again.\");\n return;\n }\n const redirect = q.get(\"redirect_uri\") ?? \"\";\n if (!c.r.includes(redirect)) {\n textErr(res, 400, \"That redirect URI isn't registered for this client.\");\n return;\n }\n const state = q.get(\"state\") ?? \"\";\n if (q.get(\"response_type\") !== \"code\" || !PKCE_RE.test(q.get(\"code_challenge\") ?? \"\") || q.get(\"code_challenge_method\") !== \"S256\") {\n // Said here, not by redirecting: anyone can register a client with\n // any https redirect, and there's no step for the person first, so\n // redirecting a bad request would make this an open redirect.\n textErr(res, 400, \"This sign-in request is incomplete: PKCE (S256) and response_type=code are required.\");\n return;\n }\n const code: GuestCode = { c: q.get(\"client_id\")!, r: redirect, s: state, p: q.get(\"code_challenge\")!, e: this.seconds() + CODE_TTL, k: true };\n let u: URL;\n try {\n u = new URL(redirect);\n } catch {\n textErr(res, 400, \"That redirect URI isn't registered for this client.\");\n return;\n }\n u.searchParams.set(\"code\", this.sign(\"code\", code));\n if (state) u.searchParams.set(\"state\", state);\n res.writeHead(302, { Location: u.toString() });\n res.end();\n }\n\n private async token(req: IncomingMessage, res: ServerResponse): Promise<void> {\n if (!this.tokens.allow(clientAddr(req, this.proxyHops), this.now())) {\n throw new OAuthFailure(429, \"slow_down\", \"too many token requests from this address; try again later\");\n }\n let f: URLSearchParams;\n try {\n f = await readForm(req, 32 << 10);\n } catch {\n throw new OAuthFailure(400, \"invalid_request\", \"bad form\");\n }\n const clientId = this.clientAuth(req, f);\n if (!clientId) {\n res.setHeader(\"WWW-Authenticate\", 'Basic realm=\"oauth\"');\n throw new OAuthFailure(401, \"invalid_client\", \"client authentication failed: send the client_id and client_secret registration gave you\");\n }\n let workspaceId: string;\n let agent: string;\n let name: string;\n let user: string;\n switch (f.get(\"grant_type\")) {\n case \"authorization_code\": {\n const c = this.open<GuestCode>(\"code\", f.get(\"code\") ?? \"\");\n if (!c || c.k !== true || typeof c.e !== \"number\" || this.seconds() > c.e || c.c !== clientId || c.r !== (f.get(\"redirect_uri\") ?? \"\")) {\n throw new OAuthFailure(400, \"invalid_grant\", \"the code is invalid or expired\");\n }\n const verifier = f.get(\"code_verifier\") ?? \"\";\n const sum = Buffer.from(createHash(\"sha256\").update(verifier).digest(\"base64url\"));\n const challenge = Buffer.from(String(c.p));\n if (!PKCE_RE.test(verifier) || sum.length !== challenge.length || !timingSafeEqual(sum, challenge)) {\n throw new OAuthFailure(400, \"invalid_grant\", \"PKCE verification failed\");\n }\n const cl = this.open<GuestClient>(\"client\", clientId)!;\n // One guest per registered client: its workspace, and its agent\n // named after the harness.\n name = cl.n;\n agent = harnessAgent(cl.n);\n user = \"guest:\" + guestId(clientId);\n try {\n workspaceId = await this.wake.workspace(user, \"Guest (\" + cl.n + \")\");\n if (this.grants) await this.wake.addAgent(workspaceId, agent, cl.n);\n } catch (err) {\n if (err instanceof WakeshiftError && err.code === \"workspace_limit\") throw new OAuthFailure(403, \"access_denied\", \"this app can't take more guests right now\");\n this.errorFn(\"wakeshift: making a guest\", err);\n throw new OAuthFailure(503, \"temporarily_unavailable\", \"couldn't sign in; try again\");\n }\n break;\n }\n case \"refresh_token\": {\n const t = this.open<GuestToken>(\"refresh\", f.get(\"refresh_token\") ?? \"\");\n if (!t || typeof t.e !== \"number\" || this.seconds() > t.e || t.i !== clientId || typeof t.w !== \"string\" || typeof t.a !== \"string\" || typeof t.u !== \"string\") {\n throw new OAuthFailure(400, \"invalid_grant\", \"the refresh token is invalid or expired\");\n }\n const guest: Guest = { user: t.u, workspace: t.w, agent: t.a, client: typeof t.c === \"string\" ? t.c : \"\", expires: new Date(t.e * 1000) };\n if (this.revokedFn && (await this.revokedFn(guest, new Date((t.t ?? 0) * 1000)))) {\n throw new OAuthFailure(400, \"invalid_grant\", \"the refresh token was revoked; sign in again\");\n }\n // The guest must still be there: forgetting the user (and, with\n // grants, revoking the grant) ends its refreshes.\n if (!(await this.stillThere(t.u, t.w, t.a, guest.client))) {\n throw new OAuthFailure(400, \"invalid_grant\", \"this guest's access was revoked; sign in again\");\n }\n workspaceId = t.w;\n agent = t.a;\n name = guest.client;\n user = t.u;\n break;\n }\n default:\n throw new OAuthFailure(400, \"unsupported_grant_type\", \"use authorization_code or refresh_token\");\n }\n const now = this.seconds();\n const access = this.sign(\"access\", { w: workspaceId, a: agent, c: name, u: user, e: now + this.accessTtl } satisfies GuestToken);\n // A new refresh token every time (rotation), dated, so revoked can\n // refuse those issued before a cutoff.\n const refresh = this.sign(\"refresh\", {\n w: workspaceId,\n a: agent,\n c: name,\n u: user,\n i: clientId,\n t: now,\n n: randomBytes(16).toString(\"base64url\"),\n e: now + this.refreshTtl,\n } satisfies GuestToken);\n res.setHeader(\"Cache-Control\", \"no-store\");\n writeJSON(res, 200, { access_token: access, token_type: \"Bearer\", expires_in: this.accessTtl, refresh_token: refresh });\n }\n\n // stillThere is whether the guest a refresh token names is still there:\n // its workspace is the one Wakeshift keeps for its user (a forgotten\n // user's is gone, so asking makes a new one, which is forgotten again at\n // once), and, with grants, its agent's grant is live. Throws a 503 when\n // Wakeshift can't say.\n private async stillThere(user: string, workspace: string, agent: string, client: string): Promise<boolean> {\n try {\n if (this.grants) {\n await this.wake.checkAgent(workspace, agent);\n return true;\n }\n if ((await this.wake.workspace(user, \"Guest (\" + client + \")\")) === workspace) return true;\n await this.wake.forgetUser(user);\n return false;\n } catch (err) {\n if (err instanceof WakeshiftError && (err.code === \"no_grant\" || err.code === \"unknown_workspace\" || err.code === \"workspace_limit\")) return false;\n this.errorFn(\"wakeshift: checking a guest\", err);\n throw new OAuthFailure(503, \"temporarily_unavailable\", \"couldn't refresh; try again\");\n }\n }\n}\n\n/** The guest ID for a client: a hash of its client_id. */\nfunction guestId(clientId: string): string {\n return createHash(\"sha256\").update(clientId).digest().subarray(0, 18).toString(\"base64url\");\n}\n\n// formUnescape is Go's url.QueryUnescape: + is a space, %XX a byte; null\n// if malformed.\nfunction formUnescape(s: string): string | null {\n if (/%(?![0-9A-Fa-f]{2})/.test(s)) return null;\n try {\n return decodeURIComponent(s.replace(/\\+/g, \" \"));\n } catch {\n return null;\n }\n}\n\nconst BAD_REDIRECT = \"redirect URIs are https, http on loopback (localhost, 127.0.0.1, [::1]) or a private-use scheme (cursor://…), without a fragment\";\n\n// validRedirect accepts https URLs, http on loopback (native apps, RFC\n// 8252) and private-use schemes (cursor://…), never ones a browser would\n// run or that carry a fragment, as the core's OAuth does.\nfunction validRedirect(raw: string): boolean {\n const m = /^([A-Za-z][A-Za-z0-9+.-]*):/.exec(raw);\n if (!m || m[1] !== m[1].toLowerCase() || raw.includes(\"#\")) return false;\n let u: URL;\n try {\n u = new URL(raw);\n } catch {\n return false;\n }\n switch (m[1]) {\n case \"https\":\n return u.hostname !== \"\";\n case \"http\":\n return u.hostname === \"localhost\" || (isIP(u.hostname) === 4 && u.hostname.startsWith(\"127.\")) || u.hostname === \"[::1]\";\n case \"javascript\":\n case \"data\":\n case \"file\":\n case \"blob\":\n case \"about\":\n case \"vbscript\":\n return false;\n }\n return true;\n}\n\nasync function readBody(req: IncomingMessage, limit: number): Promise<string> {\n const parsed = (req as IncomingMessage & { body?: unknown }).body;\n if (parsed !== undefined) return typeof parsed === \"string\" ? parsed : JSON.stringify(parsed);\n const chunks: Buffer[] = [];\n let n = 0;\n for await (const c of req) {\n n += (c as Buffer).length;\n if (n > limit) throw new Error(\"body too large\");\n chunks.push(c as Buffer);\n }\n return Buffer.concat(chunks).toString(\"utf8\");\n}\n\nasync function readJSON(req: IncomingMessage, limit: number): Promise<unknown> {\n const parsed = (req as IncomingMessage & { body?: unknown }).body;\n if (parsed !== undefined && typeof parsed === \"object\") return parsed;\n return JSON.parse(await readBody(req, limit));\n}\n\nasync function readForm(req: IncomingMessage, limit: number): Promise<URLSearchParams> {\n const parsed = (req as IncomingMessage & { body?: unknown }).body;\n if (parsed !== undefined && parsed !== null && typeof parsed === \"object\") {\n const out = new URLSearchParams();\n for (const [k, v] of Object.entries(parsed as Record<string, unknown>)) if (typeof v === \"string\") out.set(k, v);\n return out;\n }\n return new URLSearchParams(await readBody(req, limit));\n}\n\nfunction writeJSON(res: ServerResponse, status: number, v: unknown): void {\n res.statusCode = status;\n res.setHeader(\"Content-Type\", \"application/json\");\n res.end(JSON.stringify(v) + \"\\n\");\n}\n\nfunction oauthErr(res: ServerResponse, status: number, code: string, desc: string): void {\n writeJSON(res, status, { error: code, error_description: desc });\n}\n\nfunction textErr(res: ServerResponse, status: number, msg: string): void {\n res.writeHead(status, { \"Content-Type\": \"text/plain; charset=utf-8\" });\n res.end(msg + \"\\n\");\n}\n\n"]}
package/dist/limits.d.ts DELETED
@@ -1,19 +0,0 @@
1
- import type { IncomingMessage } from "node:http";
2
- /** A rate limiter: at most max events per window (ms) for each key, in memory, pruning idle keys as it goes. A negative max turns it off. */
3
- export declare class RateLimiter {
4
- readonly max: number;
5
- readonly window: number;
6
- readonly keys: number;
7
- private readonly seen;
8
- private pruned;
9
- constructor(max: number, window: number, keys?: number);
10
- allow(key: string, now: number): boolean;
11
- }
12
- /** What an address counts as for the limits: an IPv6 address's /64 (one host usually has a whole /64), anything else as it is. */
13
- export declare function limitKey(addr: string): string;
14
- /**
15
- * The request's client address: with hops trusted proxies in front (each
16
- * appending to X-Forwarded-For), the entry the outermost one added; entries
17
- * before it are the client's own claims.
18
- */
19
- export declare function clientAddr(req: IncomingMessage, hops: number): string;
package/dist/limits.js DELETED
@@ -1,105 +0,0 @@
1
- // Per-address limits for unauthenticated endpoints (GuestAuth's register
2
- // and token): who a request is from, behind trusted proxies, and how many
3
- // requests each address may make. In memory, per process.
4
- import { isIP } from "node:net";
5
- // LIMITER_KEYS bounds a limiter's memory: past it, a new address is refused
6
- // until old ones expire (the endpoints are unauthenticated, and IPv6 makes
7
- // addresses cheap).
8
- const LIMITER_KEYS = 100_000;
9
- /** A rate limiter: at most max events per window (ms) for each key, in memory, pruning idle keys as it goes. A negative max turns it off. */
10
- export class RateLimiter {
11
- max;
12
- window;
13
- keys;
14
- seen = new Map();
15
- pruned = 0;
16
- constructor(max, window, keys = LIMITER_KEYS) {
17
- this.max = max;
18
- this.window = window;
19
- this.keys = keys;
20
- }
21
- allow(key, now) {
22
- if (this.max < 0)
23
- return true;
24
- key = limitKey(key);
25
- const cut = now - this.window;
26
- const prune = () => {
27
- for (const [k, ts] of this.seen)
28
- if (ts.length === 0 || ts[ts.length - 1] <= cut)
29
- this.seen.delete(k);
30
- this.pruned = now;
31
- };
32
- if (now - this.pruned > this.window)
33
- prune();
34
- if (!this.seen.has(key) && this.seen.size >= this.keys) {
35
- prune();
36
- if (this.seen.size >= this.keys)
37
- return false;
38
- }
39
- const ts = (this.seen.get(key) ?? []).filter((t) => t > cut);
40
- if (ts.length >= this.max) {
41
- this.seen.set(key, ts);
42
- return false;
43
- }
44
- ts.push(now);
45
- this.seen.set(key, ts);
46
- return true;
47
- }
48
- }
49
- /** What an address counts as for the limits: an IPv6 address's /64 (one host usually has a whole /64), anything else as it is. */
50
- export function limitKey(addr) {
51
- const a = addr.replace(/%.*$/, "");
52
- if (isIP(a) !== 6 || /^::ffff:\d+\.\d+\.\d+\.\d+$/i.test(a))
53
- return addr;
54
- const groups = expandIPv6(a);
55
- return groups ? groups.slice(0, 4).join(":") + "::/64" : addr;
56
- }
57
- // expandIPv6 is an IPv6 address's eight groups (a dotted IPv4 tail as two).
58
- function expandIPv6(a) {
59
- let s = a.toLowerCase();
60
- const v4 = /(\d+)\.(\d+)\.(\d+)\.(\d+)$/.exec(s);
61
- if (v4) {
62
- const b = v4.slice(1).map(Number);
63
- s = s.slice(0, v4.index) + ((b[0] << 8) | b[1]).toString(16) + ":" + ((b[2] << 8) | b[3]).toString(16);
64
- }
65
- const halves = s.split("::");
66
- if (halves.length > 2)
67
- return null;
68
- const head = halves[0] ? halves[0].split(":") : [];
69
- const tail = halves.length === 2 && halves[1] ? halves[1].split(":") : [];
70
- const fill = halves.length === 2 ? 8 - head.length - tail.length : 0;
71
- const all = [...head, ...Array(Math.max(fill, 0)).fill("0"), ...tail];
72
- if (all.length !== 8)
73
- return null;
74
- return all.map((g) => parseInt(g, 16).toString(16));
75
- }
76
- /**
77
- * The request's client address: with hops trusted proxies in front (each
78
- * appending to X-Forwarded-For), the entry the outermost one added; entries
79
- * before it are the client's own claims.
80
- */
81
- export function clientAddr(req, hops) {
82
- // The first X-Forwarded-For header only, as Go's Header.Get reads it.
83
- const distinct = req.headersDistinct?.["x-forwarded-for"];
84
- const raw = req.headers["x-forwarded-for"];
85
- const f = distinct?.[0] ?? (Array.isArray(raw) ? raw[0] : raw);
86
- if (f && hops > 0) {
87
- // Only an entry the proxies added: with fewer entries than hops, or one
88
- // that isn't an address, the header isn't the proxies' (a request that
89
- // reached the app some other way), so it's ignored.
90
- const parts = f.split(",");
91
- if (parts.length >= hops) {
92
- const ip = parts[parts.length - hops].trim();
93
- if (isIP(ip))
94
- return normalizeAddr(ip);
95
- }
96
- }
97
- return normalizeAddr(req.socket?.remoteAddress ?? "");
98
- }
99
- // normalizeAddr writes an IPv4 address a dual-stack socket reports as
100
- // ::ffff:a.b.c.d as a.b.c.d, as Go does.
101
- function normalizeAddr(a) {
102
- const m = /^::ffff:(\d+\.\d+\.\d+\.\d+)$/i.exec(a);
103
- return m ? m[1] : a;
104
- }
105
- //# sourceMappingURL=limits.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"limits.js","sourceRoot":"","sources":["../src/limits.ts"],"names":[],"mappings":"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","sourcesContent":["// Per-address limits for unauthenticated endpoints (GuestAuth's register\n// and token): who a request is from, behind trusted proxies, and how many\n// requests each address may make. In memory, per process.\n\nimport type { IncomingMessage } from \"node:http\";\nimport { isIP } from \"node:net\";\n\n// LIMITER_KEYS bounds a limiter's memory: past it, a new address is refused\n// until old ones expire (the endpoints are unauthenticated, and IPv6 makes\n// addresses cheap).\nconst LIMITER_KEYS = 100_000;\n\n/** A rate limiter: at most max events per window (ms) for each key, in memory, pruning idle keys as it goes. A negative max turns it off. */\nexport class RateLimiter {\n private readonly seen = new Map<string, number[]>();\n private pruned = 0;\n\n constructor(\n readonly max: number,\n readonly window: number,\n readonly keys = LIMITER_KEYS,\n ) {}\n\n allow(key: string, now: number): boolean {\n if (this.max < 0) return true;\n key = limitKey(key);\n const cut = now - this.window;\n const prune = () => {\n for (const [k, ts] of this.seen) if (ts.length === 0 || ts[ts.length - 1] <= cut) this.seen.delete(k);\n this.pruned = now;\n };\n if (now - this.pruned > this.window) prune();\n if (!this.seen.has(key) && this.seen.size >= this.keys) {\n prune();\n if (this.seen.size >= this.keys) return false;\n }\n const ts = (this.seen.get(key) ?? []).filter((t) => t > cut);\n if (ts.length >= this.max) {\n this.seen.set(key, ts);\n return false;\n }\n ts.push(now);\n this.seen.set(key, ts);\n return true;\n }\n}\n\n/** What an address counts as for the limits: an IPv6 address's /64 (one host usually has a whole /64), anything else as it is. */\nexport function limitKey(addr: string): string {\n const a = addr.replace(/%.*$/, \"\");\n if (isIP(a) !== 6 || /^::ffff:\\d+\\.\\d+\\.\\d+\\.\\d+$/i.test(a)) return addr;\n const groups = expandIPv6(a);\n return groups ? groups.slice(0, 4).join(\":\") + \"::/64\" : addr;\n}\n\n// expandIPv6 is an IPv6 address's eight groups (a dotted IPv4 tail as two).\nfunction expandIPv6(a: string): string[] | null {\n let s = a.toLowerCase();\n const v4 = /(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)$/.exec(s);\n if (v4) {\n const b = v4.slice(1).map(Number);\n s = s.slice(0, v4.index) + ((b[0] << 8) | b[1]).toString(16) + \":\" + ((b[2] << 8) | b[3]).toString(16);\n }\n const halves = s.split(\"::\");\n if (halves.length > 2) return null;\n const head = halves[0] ? halves[0].split(\":\") : [];\n const tail = halves.length === 2 && halves[1] ? halves[1].split(\":\") : [];\n const fill = halves.length === 2 ? 8 - head.length - tail.length : 0;\n const all = [...head, ...Array(Math.max(fill, 0)).fill(\"0\"), ...tail];\n if (all.length !== 8) return null;\n return all.map((g) => parseInt(g, 16).toString(16));\n}\n\n/**\n * The request's client address: with hops trusted proxies in front (each\n * appending to X-Forwarded-For), the entry the outermost one added; entries\n * before it are the client's own claims.\n */\nexport function clientAddr(req: IncomingMessage, hops: number): string {\n // The first X-Forwarded-For header only, as Go's Header.Get reads it.\n const distinct = (req as IncomingMessage & { headersDistinct?: Record<string, string[] | undefined> }).headersDistinct?.[\"x-forwarded-for\"];\n const raw = req.headers[\"x-forwarded-for\"];\n const f = distinct?.[0] ?? (Array.isArray(raw) ? raw[0] : raw);\n if (f && hops > 0) {\n // Only an entry the proxies added: with fewer entries than hops, or one\n // that isn't an address, the header isn't the proxies' (a request that\n // reached the app some other way), so it's ignored.\n const parts = f.split(\",\");\n if (parts.length >= hops) {\n const ip = parts[parts.length - hops].trim();\n if (isIP(ip)) return normalizeAddr(ip);\n }\n }\n return normalizeAddr(req.socket?.remoteAddress ?? \"\");\n}\n\n// normalizeAddr writes an IPv4 address a dual-stack socket reports as\n// ::ffff:a.b.c.d as a.b.c.d, as Go does.\nfunction normalizeAddr(a: string): string {\n const m = /^::ffff:(\\d+\\.\\d+\\.\\d+\\.\\d+)$/i.exec(a);\n return m ? m[1] : a;\n}\n"]}
package/dist/sealed.d.ts DELETED
@@ -1,4 +0,0 @@
1
- /** The signed form of v. */
2
- export declare function seal(key: Buffer, v: unknown): string;
3
- /** The JSON object s carries, if key signed it; null for anything else. */
4
- export declare function unseal<T>(key: Buffer, s: unknown): T | null;
package/dist/sealed.js DELETED
@@ -1,38 +0,0 @@
1
- // Signed values: base64url JSON, a ".", and its HMAC-SHA256 under key, so
2
- // only the app can make one and nobody can change one. Signed, not
3
- // encrypted: whoever holds one can read it. GuestAuth's clients, codes and
4
- // tokens use these, each with its own key.
5
- import { createHmac, timingSafeEqual } from "node:crypto";
6
- const B64URL_RE = /^[A-Za-z0-9_-]*$/;
7
- /** The signed form of v. */
8
- export function seal(key, v) {
9
- const p = Buffer.from(JSON.stringify(v)).toString("base64url");
10
- return p + "." + createHmac("sha256", key).update(p).digest("base64url");
11
- }
12
- /** The JSON object s carries, if key signed it; null for anything else. */
13
- export function unseal(key, s) {
14
- if (typeof s !== "string")
15
- return null;
16
- const i = s.indexOf(".");
17
- if (i < 0)
18
- return null;
19
- const p = s.slice(0, i);
20
- const sig = s.slice(i + 1);
21
- if (!B64URL_RE.test(p) || !B64URL_RE.test(sig))
22
- return null;
23
- const got = Buffer.from(sig, "base64url");
24
- // Only the canonical encoding: no second spelling of the same signature.
25
- if (got.toString("base64url") !== sig)
26
- return null;
27
- const want = createHmac("sha256", key).update(p).digest();
28
- if (got.length !== want.length || !timingSafeEqual(got, want))
29
- return null;
30
- try {
31
- const v = JSON.parse(Buffer.from(p, "base64url").toString("utf8"));
32
- return v !== null && typeof v === "object" && !Array.isArray(v) ? v : null;
33
- }
34
- catch {
35
- return null;
36
- }
37
- }
38
- //# sourceMappingURL=sealed.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sealed.js","sourceRoot":"","sources":["../src/sealed.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,mEAAmE;AACnE,2EAA2E;AAC3E,2CAA2C;AAE3C,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE1D,MAAM,SAAS,GAAG,kBAAkB,CAAC;AAErC,4BAA4B;AAC5B,MAAM,UAAU,IAAI,CAAC,GAAW,EAAE,CAAU;IAC1C,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAC/D,OAAO,CAAC,GAAG,GAAG,GAAG,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;AAC3E,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,MAAM,CAAI,GAAW,EAAE,CAAU;IAC/C,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACvC,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACzB,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACvB,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACxB,MAAM,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAC5D,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IAC1C,yEAAyE;IACzE,IAAI,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,KAAK,GAAG;QAAE,OAAO,IAAI,CAAC;IACnD,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAC1D,IAAI,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,IAAI,CAAC,eAAe,CAAC,GAAG,EAAE,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3E,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;QACnE,OAAO,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAE,CAAO,CAAC,CAAC,CAAC,IAAI,CAAC;IACpF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC","sourcesContent":["// Signed values: base64url JSON, a \".\", and its HMAC-SHA256 under key, so\n// only the app can make one and nobody can change one. Signed, not\n// encrypted: whoever holds one can read it. GuestAuth's clients, codes and\n// tokens use these, each with its own key.\n\nimport { createHmac, timingSafeEqual } from \"node:crypto\";\n\nconst B64URL_RE = /^[A-Za-z0-9_-]*$/;\n\n/** The signed form of v. */\nexport function seal(key: Buffer, v: unknown): string {\n const p = Buffer.from(JSON.stringify(v)).toString(\"base64url\");\n return p + \".\" + createHmac(\"sha256\", key).update(p).digest(\"base64url\");\n}\n\n/** The JSON object s carries, if key signed it; null for anything else. */\nexport function unseal<T>(key: Buffer, s: unknown): T | null {\n if (typeof s !== \"string\") return null;\n const i = s.indexOf(\".\");\n if (i < 0) return null;\n const p = s.slice(0, i);\n const sig = s.slice(i + 1);\n if (!B64URL_RE.test(p) || !B64URL_RE.test(sig)) return null;\n const got = Buffer.from(sig, \"base64url\");\n // Only the canonical encoding: no second spelling of the same signature.\n if (got.toString(\"base64url\") !== sig) return null;\n const want = createHmac(\"sha256\", key).update(p).digest();\n if (got.length !== want.length || !timingSafeEqual(got, want)) return null;\n try {\n const v = JSON.parse(Buffer.from(p, \"base64url\").toString(\"utf8\"));\n return v !== null && typeof v === \"object\" && !Array.isArray(v) ? (v as T) : null;\n } catch {\n return null;\n }\n}\n"]}