cauthy-auth 0.5.2 → 0.8.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.
Files changed (72) hide show
  1. package/README.md +68 -3
  2. package/dist/{cauthy-BCTCqubt.d.ts → cauthy-Bn3iv50y.d.ts} +1 -1
  3. package/dist/{cauthy-hswMoS7B.d.mts → cauthy-C29HCvag.d.mts} +1 -1
  4. package/dist/cli.js +490 -25
  5. package/dist/client.d.mts +236 -0
  6. package/dist/client.d.ts +236 -0
  7. package/dist/client.js +331 -0
  8. package/dist/client.js.map +1 -0
  9. package/dist/client.mjs +297 -0
  10. package/dist/client.mjs.map +1 -0
  11. package/dist/express.d.mts +24 -0
  12. package/dist/express.d.ts +24 -0
  13. package/dist/express.js +102 -0
  14. package/dist/express.js.map +1 -0
  15. package/dist/express.mjs +76 -0
  16. package/dist/express.mjs.map +1 -0
  17. package/dist/fastify.d.mts +2 -2
  18. package/dist/fastify.d.ts +2 -2
  19. package/dist/fastify.js +3 -1
  20. package/dist/fastify.js.map +1 -1
  21. package/dist/fastify.mjs +3 -1
  22. package/dist/fastify.mjs.map +1 -1
  23. package/dist/hono.d.mts +23 -0
  24. package/dist/hono.d.ts +23 -0
  25. package/dist/hono.js +50 -0
  26. package/dist/hono.js.map +1 -0
  27. package/dist/hono.mjs +24 -0
  28. package/dist/hono.mjs.map +1 -0
  29. package/dist/index.d.mts +44 -6
  30. package/dist/index.d.ts +44 -6
  31. package/dist/index.js +668 -37
  32. package/dist/index.js.map +1 -1
  33. package/dist/index.mjs +656 -37
  34. package/dist/index.mjs.map +1 -1
  35. package/dist/next.d.mts +24 -0
  36. package/dist/next.d.ts +24 -0
  37. package/dist/next.js +77 -0
  38. package/dist/next.js.map +1 -0
  39. package/dist/next.mjs +52 -0
  40. package/dist/next.mjs.map +1 -0
  41. package/dist/react.d.mts +546 -7
  42. package/dist/react.d.ts +546 -7
  43. package/dist/react.js +925 -14
  44. package/dist/react.js.map +1 -1
  45. package/dist/react.mjs +913 -10
  46. package/dist/react.mjs.map +1 -1
  47. package/dist/styles.css +271 -0
  48. package/dist/svelte.d.mts +26 -0
  49. package/dist/svelte.d.ts +26 -0
  50. package/dist/svelte.js +402 -0
  51. package/dist/svelte.js.map +1 -0
  52. package/dist/svelte.mjs +373 -0
  53. package/dist/svelte.mjs.map +1 -0
  54. package/dist/{system-DvcQjORr.d.ts → system-DhRr_WxR.d.ts} +139 -1
  55. package/dist/{system-CR8p4BjB.d.mts → system-ZD_Wa8Bm.d.mts} +139 -1
  56. package/dist/theme.d.mts +56 -1
  57. package/dist/theme.d.ts +56 -1
  58. package/dist/theme.js +181 -5
  59. package/dist/theme.js.map +1 -1
  60. package/dist/theme.mjs +176 -4
  61. package/dist/theme.mjs.map +1 -1
  62. package/dist/validate-B_iC-4y8.d.mts +19 -0
  63. package/dist/validate-B_iC-4y8.d.ts +19 -0
  64. package/dist/vue.d.mts +28 -0
  65. package/dist/vue.d.ts +28 -0
  66. package/dist/vue.js +420 -0
  67. package/dist/vue.js.map +1 -0
  68. package/dist/vue.mjs +391 -0
  69. package/dist/vue.mjs.map +1 -0
  70. package/package.json +68 -7
  71. package/dist/permissions-B-a3eN0h.d.mts +0 -52
  72. package/dist/permissions-B-a3eN0h.d.ts +0 -52
@@ -0,0 +1,76 @@
1
+ // src/express.ts
2
+ function originOf(req) {
3
+ const secure = req.socket?.encrypted === true;
4
+ return `${req.protocol ?? (secure ? "https" : "http")}://${req.headers.host ?? "localhost"}`;
5
+ }
6
+ async function bodyOf(req) {
7
+ if (req.method === "GET" || req.method === "HEAD") return void 0;
8
+ if (req.body !== void 0 && req.body !== null) {
9
+ if (typeof req.body === "string") return req.body;
10
+ if (req.body instanceof Uint8Array) return new Uint8Array(req.body);
11
+ return JSON.stringify(req.body);
12
+ }
13
+ const chunks = [];
14
+ for await (const chunk of req) chunks.push(typeof chunk === "string" ? new TextEncoder().encode(chunk) : chunk);
15
+ return chunks.length === 0 ? void 0 : new Blob(chunks);
16
+ }
17
+ async function toWebRequest(req, withBody) {
18
+ const headers = new Headers();
19
+ for (const [k, v] of Object.entries(req.headers)) {
20
+ if (Array.isArray(v)) for (const one of v) headers.append(k, one);
21
+ else if (v !== void 0) headers.set(k, v);
22
+ }
23
+ if (typeof req.ip === "string" && req.ip !== "") headers.set("x-forwarded-for", req.ip);
24
+ return new Request(new URL(req.originalUrl ?? req.url ?? "/", originOf(req)), {
25
+ method: req.method,
26
+ headers,
27
+ body: withBody ? await bodyOf(req) : void 0
28
+ });
29
+ }
30
+ function addCookies(res, cookies) {
31
+ if (cookies.length === 0 || res.headersSent) return;
32
+ const had = res.getHeader("set-cookie");
33
+ res.setHeader("set-cookie", [...Array.isArray(had) ? had : typeof had === "string" ? [had] : [], ...cookies]);
34
+ }
35
+ function cauthyExpress(auth) {
36
+ const base = auth.options.basePath;
37
+ return function cauthy(req, res, next) {
38
+ const request = req;
39
+ const path = (request.originalUrl ?? request.url ?? "/").split("?")[0];
40
+ if (path === base || path.startsWith(`${base}/`)) {
41
+ void (async () => {
42
+ const answer = await auth.handler(await toWebRequest(request, true));
43
+ res.statusCode = answer.status;
44
+ answer.headers.forEach((value, name) => {
45
+ if (name !== "set-cookie") res.setHeader(name, value);
46
+ });
47
+ addCookies(res, answer.headers.getSetCookie());
48
+ res.end(answer.body === null ? void 0 : Buffer.from(await answer.arrayBuffer()));
49
+ })().catch(next);
50
+ return;
51
+ }
52
+ let asked;
53
+ request.cauthy = () => asked ??= (async () => {
54
+ const resolved = await auth.resolve(await toWebRequest(request, false));
55
+ addCookies(res, resolved.cookies);
56
+ return resolved.session;
57
+ })();
58
+ next();
59
+ };
60
+ }
61
+ function requireSession(req, res, next) {
62
+ const ask = req.cauthy;
63
+ if (!ask) return next(new Error("cauthy-auth: mount cauthyExpress(auth) before requireSession"));
64
+ ask().then((session) => {
65
+ if (session !== null) return next();
66
+ res.statusCode = 401;
67
+ res.setHeader("content-type", "application/json; charset=utf-8");
68
+ res.setHeader("x-cauthy-session", "none");
69
+ res.end(JSON.stringify({ error: "unauthenticated" }));
70
+ }, next);
71
+ }
72
+ export {
73
+ cauthyExpress,
74
+ requireSession
75
+ };
76
+ //# sourceMappingURL=express.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/express.ts"],"sourcesContent":["// Express (and anything else that speaks Node's http): the routes, and who is\n// signed in on every request.\n//\n// app.use(cauthyExpress(auth))\n//\n// app.get('/api/me', async (req, res) => {\n// const session = await req.cauthy()\n// if (!session) return res.status(401).json({ error: 'unauthenticated' })\n// res.json(session.user)\n// })\n//\n// app.get('/api/books', requireSession, (req, res) => { … })\n//\n// A session that needs renewing is renewed on the spot, and its new cookie\n// leaves with whatever the route answers.\n\nimport type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { Cauthy } from './cauthy'\nimport type { Session } from './types'\n\ndeclare global {\n // eslint-disable-next-line @typescript-eslint/no-namespace\n namespace Express {\n interface Request {\n /** Who is signed in, or null. Asked once per request. */\n cauthy(): Promise<Session | null>\n }\n }\n}\n\n/** A request as Node gives it, with what Express adds when it is Express. */\ntype NodeRequest = IncomingMessage & { originalUrl?: string; protocol?: string; ip?: string; body?: unknown; cauthy?: () => Promise<Session | null> }\ntype Next = (error?: unknown) => void\n\nfunction originOf(req: NodeRequest): string {\n const secure = (req.socket as { encrypted?: boolean } | undefined)?.encrypted === true\n return `${req.protocol ?? (secure ? 'https' : 'http')}://${req.headers.host ?? 'localhost'}`\n}\n\nasync function bodyOf(req: NodeRequest): Promise<BodyInit | undefined> {\n if (req.method === 'GET' || req.method === 'HEAD') return undefined\n // A body parser was here first (express.json()): what it read is the body.\n if (req.body !== undefined && req.body !== null) {\n if (typeof req.body === 'string') return req.body\n if (req.body instanceof Uint8Array) return new Uint8Array(req.body)\n return JSON.stringify(req.body)\n }\n const chunks: Uint8Array[] = []\n for await (const chunk of req) chunks.push(typeof chunk === 'string' ? new TextEncoder().encode(chunk) : (chunk as Uint8Array))\n return chunks.length === 0 ? undefined : new Blob(chunks as BlobPart[])\n}\n\nasync function toWebRequest(req: NodeRequest, withBody: boolean): Promise<Request> {\n const headers = new Headers()\n for (const [k, v] of Object.entries(req.headers)) {\n if (Array.isArray(v)) for (const one of v) headers.append(k, one)\n else if (v !== undefined) headers.set(k, v)\n }\n // Express knows who is calling (it applies `trust proxy`): that address is\n // the one passed on to Cauthy, whatever the header claimed.\n if (typeof req.ip === 'string' && req.ip !== '') headers.set('x-forwarded-for', req.ip)\n return new Request(new URL(req.originalUrl ?? req.url ?? '/', originOf(req)), {\n method: req.method,\n headers,\n body: withBody ? await bodyOf(req) : undefined,\n })\n}\n\nfunction addCookies(res: ServerResponse, cookies: string[]): void {\n if (cookies.length === 0 || res.headersSent) return\n const had = res.getHeader('set-cookie')\n res.setHeader('set-cookie', [...(Array.isArray(had) ? had : typeof had === 'string' ? [had] : []), ...cookies])\n}\n\n/**\n * Serves the routes under the handler's `basePath`, and gives every other\n * request `req.cauthy()`. Mount it once, before the routes that use it.\n */\nexport function cauthyExpress(auth: Cauthy) {\n const base = auth.options.basePath\n return function cauthy(req: IncomingMessage, res: ServerResponse, next: Next): void {\n const request = req as NodeRequest\n const path = (request.originalUrl ?? request.url ?? '/').split('?')[0]\n\n if (path === base || path.startsWith(`${base}/`)) {\n void (async () => {\n const answer = await auth.handler(await toWebRequest(request, true))\n res.statusCode = answer.status\n answer.headers.forEach((value, name) => {\n if (name !== 'set-cookie') res.setHeader(name, value)\n })\n addCookies(res, answer.headers.getSetCookie())\n res.end(answer.body === null ? undefined : Buffer.from(await answer.arrayBuffer()))\n })().catch(next)\n return\n }\n\n let asked: Promise<Session | null> | undefined\n request.cauthy = () =>\n (asked ??= (async () => {\n const resolved = await auth.resolve(await toWebRequest(request, false))\n addCookies(res, resolved.cookies)\n return resolved.session\n })())\n next()\n }\n}\n\n/** For a route only a signed-in person may call: answers 401 otherwise. Needs `cauthyExpress` mounted before it. */\nexport function requireSession(req: IncomingMessage, res: ServerResponse, next: Next): void {\n const ask = (req as NodeRequest).cauthy\n if (!ask) return next(new Error('cauthy-auth: mount cauthyExpress(auth) before requireSession'))\n ask().then((session) => {\n if (session !== null) return next()\n res.statusCode = 401\n res.setHeader('content-type', 'application/json; charset=utf-8')\n res.setHeader('x-cauthy-session', 'none')\n res.end(JSON.stringify({ error: 'unauthenticated' }))\n }, next)\n}\n"],"mappings":";AAkCA,SAAS,SAAS,KAA0B;AAC1C,QAAM,SAAU,IAAI,QAAgD,cAAc;AAClF,SAAO,GAAG,IAAI,aAAa,SAAS,UAAU,OAAO,MAAM,IAAI,QAAQ,QAAQ,WAAW;AAC5F;AAEA,eAAe,OAAO,KAAiD;AACrE,MAAI,IAAI,WAAW,SAAS,IAAI,WAAW,OAAQ,QAAO;AAE1D,MAAI,IAAI,SAAS,UAAa,IAAI,SAAS,MAAM;AAC/C,QAAI,OAAO,IAAI,SAAS,SAAU,QAAO,IAAI;AAC7C,QAAI,IAAI,gBAAgB,WAAY,QAAO,IAAI,WAAW,IAAI,IAAI;AAClE,WAAO,KAAK,UAAU,IAAI,IAAI;AAAA,EAChC;AACA,QAAM,SAAuB,CAAC;AAC9B,mBAAiB,SAAS,IAAK,QAAO,KAAK,OAAO,UAAU,WAAW,IAAI,YAAY,EAAE,OAAO,KAAK,IAAK,KAAoB;AAC9H,SAAO,OAAO,WAAW,IAAI,SAAY,IAAI,KAAK,MAAoB;AACxE;AAEA,eAAe,aAAa,KAAkB,UAAqC;AACjF,QAAM,UAAU,IAAI,QAAQ;AAC5B,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,IAAI,OAAO,GAAG;AAChD,QAAI,MAAM,QAAQ,CAAC,EAAG,YAAW,OAAO,EAAG,SAAQ,OAAO,GAAG,GAAG;AAAA,aACvD,MAAM,OAAW,SAAQ,IAAI,GAAG,CAAC;AAAA,EAC5C;AAGA,MAAI,OAAO,IAAI,OAAO,YAAY,IAAI,OAAO,GAAI,SAAQ,IAAI,mBAAmB,IAAI,EAAE;AACtF,SAAO,IAAI,QAAQ,IAAI,IAAI,IAAI,eAAe,IAAI,OAAO,KAAK,SAAS,GAAG,CAAC,GAAG;AAAA,IAC5E,QAAQ,IAAI;AAAA,IACZ;AAAA,IACA,MAAM,WAAW,MAAM,OAAO,GAAG,IAAI;AAAA,EACvC,CAAC;AACH;AAEA,SAAS,WAAW,KAAqB,SAAyB;AAChE,MAAI,QAAQ,WAAW,KAAK,IAAI,YAAa;AAC7C,QAAM,MAAM,IAAI,UAAU,YAAY;AACtC,MAAI,UAAU,cAAc,CAAC,GAAI,MAAM,QAAQ,GAAG,IAAI,MAAM,OAAO,QAAQ,WAAW,CAAC,GAAG,IAAI,CAAC,GAAI,GAAG,OAAO,CAAC;AAChH;AAMO,SAAS,cAAc,MAAc;AAC1C,QAAM,OAAO,KAAK,QAAQ;AAC1B,SAAO,SAAS,OAAO,KAAsB,KAAqB,MAAkB;AAClF,UAAM,UAAU;AAChB,UAAM,QAAQ,QAAQ,eAAe,QAAQ,OAAO,KAAK,MAAM,GAAG,EAAE,CAAC;AAErE,QAAI,SAAS,QAAQ,KAAK,WAAW,GAAG,IAAI,GAAG,GAAG;AAChD,YAAM,YAAY;AAChB,cAAM,SAAS,MAAM,KAAK,QAAQ,MAAM,aAAa,SAAS,IAAI,CAAC;AACnE,YAAI,aAAa,OAAO;AACxB,eAAO,QAAQ,QAAQ,CAAC,OAAO,SAAS;AACtC,cAAI,SAAS,aAAc,KAAI,UAAU,MAAM,KAAK;AAAA,QACtD,CAAC;AACD,mBAAW,KAAK,OAAO,QAAQ,aAAa,CAAC;AAC7C,YAAI,IAAI,OAAO,SAAS,OAAO,SAAY,OAAO,KAAK,MAAM,OAAO,YAAY,CAAC,CAAC;AAAA,MACpF,GAAG,EAAE,MAAM,IAAI;AACf;AAAA,IACF;AAEA,QAAI;AACJ,YAAQ,SAAS,MACd,WAAW,YAAY;AACtB,YAAM,WAAW,MAAM,KAAK,QAAQ,MAAM,aAAa,SAAS,KAAK,CAAC;AACtE,iBAAW,KAAK,SAAS,OAAO;AAChC,aAAO,SAAS;AAAA,IAClB,GAAG;AACL,SAAK;AAAA,EACP;AACF;AAGO,SAAS,eAAe,KAAsB,KAAqB,MAAkB;AAC1F,QAAM,MAAO,IAAoB;AACjC,MAAI,CAAC,IAAK,QAAO,KAAK,IAAI,MAAM,8DAA8D,CAAC;AAC/F,MAAI,EAAE,KAAK,CAAC,YAAY;AACtB,QAAI,YAAY,KAAM,QAAO,KAAK;AAClC,QAAI,aAAa;AACjB,QAAI,UAAU,gBAAgB,iCAAiC;AAC/D,QAAI,UAAU,oBAAoB,MAAM;AACxC,QAAI,IAAI,KAAK,UAAU,EAAE,OAAO,kBAAkB,CAAC,CAAC;AAAA,EACtD,GAAG,IAAI;AACT;","names":[]}
@@ -1,6 +1,6 @@
1
1
  import { FastifyReply, FastifyPluginAsync } from 'fastify';
2
- import { C as Cauthy } from './cauthy-hswMoS7B.mjs';
3
- import { S as Session } from './system-CR8p4BjB.mjs';
2
+ import { C as Cauthy } from './cauthy-C29HCvag.mjs';
3
+ import { S as Session } from './system-ZD_Wa8Bm.mjs';
4
4
  import 'jose';
5
5
  import './theme.mjs';
6
6
 
package/dist/fastify.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { FastifyReply, FastifyPluginAsync } from 'fastify';
2
- import { C as Cauthy } from './cauthy-BCTCqubt.js';
3
- import { S as Session } from './system-DvcQjORr.js';
2
+ import { C as Cauthy } from './cauthy-Bn3iv50y.js';
3
+ import { S as Session } from './system-DhRr_WxR.js';
4
4
  import 'jose';
5
5
  import './theme.js';
6
6
 
package/dist/fastify.js CHANGED
@@ -33,7 +33,9 @@ function toWebRequest(req) {
33
33
  if (Array.isArray(v)) for (const one of v) headers.append(k, one);
34
34
  else if (v !== void 0) headers.set(k, v);
35
35
  }
36
- return new Request(new URL(req.url, originOf(req)), { method: req.method, headers });
36
+ headers.set("x-forwarded-for", req.ip);
37
+ const body = req.method === "GET" || req.method === "HEAD" || req.body === void 0 || req.body === null ? void 0 : typeof req.body === "string" ? req.body : JSON.stringify(req.body);
38
+ return new Request(new URL(req.url, originOf(req)), { method: req.method, headers, body });
37
39
  }
38
40
  var kSession = /* @__PURE__ */ Symbol("cauthy.session");
39
41
  var kReply = /* @__PURE__ */ Symbol("cauthy.reply");
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/fastify.ts"],"sourcesContent":["// Fastify: the routes, and who is signed in on every request.\n//\n// await app.register(cauthyFastify, { auth })\n//\n// app.get('/api/me', async (req, reply) => {\n// const session = await req.cauthy()\n// if (!session) return reply.code(401).send({ error: 'unauthenticated' })\n// return session.user\n// })\n//\n// app.get('/api/books', { preHandler: app.requireSession }, async (req) => { … })\n//\n// Here a session that needs renewing is renewed on the spot: Fastify has the\n// reply in hand, so the new cookie always goes back.\n\nimport type { FastifyInstance, FastifyPluginAsync, FastifyReply, FastifyRequest } from 'fastify'\nimport type { Cauthy } from './cauthy'\nimport type { Session } from './types'\n\ndeclare module 'fastify' {\n interface FastifyRequest {\n /** Who is signed in, or null. Asked once per request. */\n cauthy(): Promise<Session | null>\n }\n interface FastifyInstance {\n /** A preHandler that answers 401 unless somebody is signed in. */\n requireSession(request: FastifyRequest, reply: FastifyReply): Promise<void>\n }\n}\n\nexport interface CauthyFastifyOptions {\n auth: Cauthy\n}\n\nfunction originOf(req: FastifyRequest): string {\n return `${req.protocol}://${req.headers.host ?? 'localhost'}`\n}\n\nfunction toWebRequest(req: FastifyRequest): Request {\n const headers = new Headers()\n for (const [k, v] of Object.entries(req.headers)) {\n if (Array.isArray(v)) for (const one of v) headers.append(k, one)\n else if (v !== undefined) headers.set(k, v)\n }\n // The routes read no body: what they need is in the URL and the cookies.\n return new Request(new URL(req.url, originOf(req)), { method: req.method, headers })\n}\n\nconst kSession = Symbol('cauthy.session')\nconst kReply = Symbol('cauthy.reply')\n\nconst plugin: FastifyPluginAsync<CauthyFastifyOptions> = async (app: FastifyInstance, { auth }) => {\n const base = auth.options.basePath\n\n app.decorateRequest('cauthy', async function (this: FastifyRequest): Promise<Session | null> {\n const self = this as FastifyRequest & { [kSession]?: Promise<Session | null> }\n self[kSession] ??= (async () => {\n const resolved = await auth.resolve(toWebRequest(this))\n // Set through the raw response so the cookie leaves whatever the route\n // answers with, even an error.\n const reply = (this as FastifyRequest & { [kReply]?: FastifyReply })[kReply]\n if (resolved.cookies.length > 0 && reply) reply.header('set-cookie', resolved.cookies)\n return resolved.session\n })()\n return self[kSession]\n })\n\n app.addHook('onRequest', async (req, reply) => {\n ;(req as FastifyRequest & { [kReply]?: FastifyReply })[kReply] = reply\n })\n\n app.decorate('requireSession', async function (request: FastifyRequest, reply: FastifyReply): Promise<void> {\n if ((await request.cauthy()) === null) {\n await reply.code(401).header('x-cauthy-session', 'none').send({ error: 'unauthenticated' })\n }\n })\n\n const serve = async (req: FastifyRequest, reply: FastifyReply) => {\n const res = await auth.handler(toWebRequest(req))\n reply.code(res.status)\n res.headers.forEach((value, name) => {\n if (name !== 'set-cookie') reply.header(name, value)\n })\n const cookies = res.headers.getSetCookie()\n if (cookies.length > 0) reply.header('set-cookie', cookies)\n return reply.send(res.body === null ? null : Buffer.from(await res.arrayBuffer()))\n }\n app.route({ method: ['GET', 'POST'], url: `${base}/*`, handler: serve })\n}\n\n\n// Outside encapsulation: `req.cauthy()` and `requireSession` are for the whole\n// application, not only for routes registered beside this plugin.\n;(plugin as unknown as Record<symbol, boolean>)[Symbol.for('skip-override')] = true\n;(plugin as unknown as Record<symbol, unknown>)[Symbol.for('fastify.display-name')] = 'cauthy-auth'\n\nexport const cauthyFastify = plugin\nexport default plugin\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkCA,SAAS,SAAS,KAA6B;AAC7C,SAAO,GAAG,IAAI,QAAQ,MAAM,IAAI,QAAQ,QAAQ,WAAW;AAC7D;AAEA,SAAS,aAAa,KAA8B;AAClD,QAAM,UAAU,IAAI,QAAQ;AAC5B,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,IAAI,OAAO,GAAG;AAChD,QAAI,MAAM,QAAQ,CAAC,EAAG,YAAW,OAAO,EAAG,SAAQ,OAAO,GAAG,GAAG;AAAA,aACvD,MAAM,OAAW,SAAQ,IAAI,GAAG,CAAC;AAAA,EAC5C;AAEA,SAAO,IAAI,QAAQ,IAAI,IAAI,IAAI,KAAK,SAAS,GAAG,CAAC,GAAG,EAAE,QAAQ,IAAI,QAAQ,QAAQ,CAAC;AACrF;AAEA,IAAM,WAAW,uBAAO,gBAAgB;AACxC,IAAM,SAAS,uBAAO,cAAc;AAEpC,IAAM,SAAmD,OAAO,KAAsB,EAAE,KAAK,MAAM;AACjG,QAAM,OAAO,KAAK,QAAQ;AAE1B,MAAI,gBAAgB,UAAU,iBAA+D;AAC3F,UAAM,OAAO;AACb,SAAK,QAAQ,OAAO,YAAY;AAC9B,YAAM,WAAW,MAAM,KAAK,QAAQ,aAAa,IAAI,CAAC;AAGtD,YAAM,QAAS,KAAsD,MAAM;AAC3E,UAAI,SAAS,QAAQ,SAAS,KAAK,MAAO,OAAM,OAAO,cAAc,SAAS,OAAO;AACrF,aAAO,SAAS;AAAA,IAClB,GAAG;AACH,WAAO,KAAK,QAAQ;AAAA,EACtB,CAAC;AAED,MAAI,QAAQ,aAAa,OAAO,KAAK,UAAU;AAC7C;AAAC,IAAC,IAAqD,MAAM,IAAI;AAAA,EACnE,CAAC;AAED,MAAI,SAAS,kBAAkB,eAAgB,SAAyB,OAAoC;AAC1G,QAAK,MAAM,QAAQ,OAAO,MAAO,MAAM;AACrC,YAAM,MAAM,KAAK,GAAG,EAAE,OAAO,oBAAoB,MAAM,EAAE,KAAK,EAAE,OAAO,kBAAkB,CAAC;AAAA,IAC5F;AAAA,EACF,CAAC;AAED,QAAM,QAAQ,OAAO,KAAqB,UAAwB;AAChE,UAAM,MAAM,MAAM,KAAK,QAAQ,aAAa,GAAG,CAAC;AAChD,UAAM,KAAK,IAAI,MAAM;AACrB,QAAI,QAAQ,QAAQ,CAAC,OAAO,SAAS;AACnC,UAAI,SAAS,aAAc,OAAM,OAAO,MAAM,KAAK;AAAA,IACrD,CAAC;AACD,UAAM,UAAU,IAAI,QAAQ,aAAa;AACzC,QAAI,QAAQ,SAAS,EAAG,OAAM,OAAO,cAAc,OAAO;AAC1D,WAAO,MAAM,KAAK,IAAI,SAAS,OAAO,OAAO,OAAO,KAAK,MAAM,IAAI,YAAY,CAAC,CAAC;AAAA,EACnF;AACA,MAAI,MAAM,EAAE,QAAQ,CAAC,OAAO,MAAM,GAAG,KAAK,GAAG,IAAI,MAAM,SAAS,MAAM,CAAC;AACzE;AAKE,OAA8C,uBAAO,IAAI,eAAe,CAAC,IAAI;AAC7E,OAA8C,uBAAO,IAAI,sBAAsB,CAAC,IAAI;AAE/E,IAAM,gBAAgB;AAC7B,IAAO,kBAAQ;","names":[]}
1
+ {"version":3,"sources":["../src/fastify.ts"],"sourcesContent":["// Fastify: the routes, and who is signed in on every request.\n//\n// await app.register(cauthyFastify, { auth })\n//\n// app.get('/api/me', async (req, reply) => {\n// const session = await req.cauthy()\n// if (!session) return reply.code(401).send({ error: 'unauthenticated' })\n// return session.user\n// })\n//\n// app.get('/api/books', { preHandler: app.requireSession }, async (req) => { … })\n//\n// Here a session that needs renewing is renewed on the spot: Fastify has the\n// reply in hand, so the new cookie always goes back.\n\nimport type { FastifyInstance, FastifyPluginAsync, FastifyReply, FastifyRequest } from 'fastify'\nimport type { Cauthy } from './cauthy'\nimport type { Session } from './types'\n\ndeclare module 'fastify' {\n interface FastifyRequest {\n /** Who is signed in, or null. Asked once per request. */\n cauthy(): Promise<Session | null>\n }\n interface FastifyInstance {\n /** A preHandler that answers 401 unless somebody is signed in. */\n requireSession(request: FastifyRequest, reply: FastifyReply): Promise<void>\n }\n}\n\nexport interface CauthyFastifyOptions {\n auth: Cauthy\n}\n\nfunction originOf(req: FastifyRequest): string {\n return `${req.protocol}://${req.headers.host ?? 'localhost'}`\n}\n\nfunction toWebRequest(req: FastifyRequest): Request {\n const headers = new Headers()\n for (const [k, v] of Object.entries(req.headers)) {\n if (Array.isArray(v)) for (const one of v) headers.append(k, one)\n else if (v !== undefined) headers.set(k, v)\n }\n // Fastify knows who is calling (it applies `trustProxy`): that address is\n // the one passed on to Cauthy, whatever the header claimed.\n headers.set('x-forwarded-for', req.ip)\n // What Fastify parsed is the body: the application's own sign-in screens post JSON.\n const body = req.method === 'GET' || req.method === 'HEAD' || req.body === undefined || req.body === null\n ? undefined\n : typeof req.body === 'string' ? req.body : JSON.stringify(req.body)\n return new Request(new URL(req.url, originOf(req)), { method: req.method, headers, body })\n}\n\nconst kSession = Symbol('cauthy.session')\nconst kReply = Symbol('cauthy.reply')\n\nconst plugin: FastifyPluginAsync<CauthyFastifyOptions> = async (app: FastifyInstance, { auth }) => {\n const base = auth.options.basePath\n\n app.decorateRequest('cauthy', async function (this: FastifyRequest): Promise<Session | null> {\n const self = this as FastifyRequest & { [kSession]?: Promise<Session | null> }\n self[kSession] ??= (async () => {\n const resolved = await auth.resolve(toWebRequest(this))\n // Set through the raw response so the cookie leaves whatever the route\n // answers with, even an error.\n const reply = (this as FastifyRequest & { [kReply]?: FastifyReply })[kReply]\n if (resolved.cookies.length > 0 && reply) reply.header('set-cookie', resolved.cookies)\n return resolved.session\n })()\n return self[kSession]\n })\n\n app.addHook('onRequest', async (req, reply) => {\n ;(req as FastifyRequest & { [kReply]?: FastifyReply })[kReply] = reply\n })\n\n app.decorate('requireSession', async function (request: FastifyRequest, reply: FastifyReply): Promise<void> {\n if ((await request.cauthy()) === null) {\n await reply.code(401).header('x-cauthy-session', 'none').send({ error: 'unauthenticated' })\n }\n })\n\n const serve = async (req: FastifyRequest, reply: FastifyReply) => {\n const res = await auth.handler(toWebRequest(req))\n reply.code(res.status)\n res.headers.forEach((value, name) => {\n if (name !== 'set-cookie') reply.header(name, value)\n })\n const cookies = res.headers.getSetCookie()\n if (cookies.length > 0) reply.header('set-cookie', cookies)\n return reply.send(res.body === null ? null : Buffer.from(await res.arrayBuffer()))\n }\n app.route({ method: ['GET', 'POST'], url: `${base}/*`, handler: serve })\n}\n\n\n// Outside encapsulation: `req.cauthy()` and `requireSession` are for the whole\n// application, not only for routes registered beside this plugin.\n;(plugin as unknown as Record<symbol, boolean>)[Symbol.for('skip-override')] = true\n;(plugin as unknown as Record<symbol, unknown>)[Symbol.for('fastify.display-name')] = 'cauthy-auth'\n\nexport const cauthyFastify = plugin\nexport default plugin\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkCA,SAAS,SAAS,KAA6B;AAC7C,SAAO,GAAG,IAAI,QAAQ,MAAM,IAAI,QAAQ,QAAQ,WAAW;AAC7D;AAEA,SAAS,aAAa,KAA8B;AAClD,QAAM,UAAU,IAAI,QAAQ;AAC5B,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,IAAI,OAAO,GAAG;AAChD,QAAI,MAAM,QAAQ,CAAC,EAAG,YAAW,OAAO,EAAG,SAAQ,OAAO,GAAG,GAAG;AAAA,aACvD,MAAM,OAAW,SAAQ,IAAI,GAAG,CAAC;AAAA,EAC5C;AAGA,UAAQ,IAAI,mBAAmB,IAAI,EAAE;AAErC,QAAM,OAAO,IAAI,WAAW,SAAS,IAAI,WAAW,UAAU,IAAI,SAAS,UAAa,IAAI,SAAS,OACjG,SACA,OAAO,IAAI,SAAS,WAAW,IAAI,OAAO,KAAK,UAAU,IAAI,IAAI;AACrE,SAAO,IAAI,QAAQ,IAAI,IAAI,IAAI,KAAK,SAAS,GAAG,CAAC,GAAG,EAAE,QAAQ,IAAI,QAAQ,SAAS,KAAK,CAAC;AAC3F;AAEA,IAAM,WAAW,uBAAO,gBAAgB;AACxC,IAAM,SAAS,uBAAO,cAAc;AAEpC,IAAM,SAAmD,OAAO,KAAsB,EAAE,KAAK,MAAM;AACjG,QAAM,OAAO,KAAK,QAAQ;AAE1B,MAAI,gBAAgB,UAAU,iBAA+D;AAC3F,UAAM,OAAO;AACb,SAAK,QAAQ,OAAO,YAAY;AAC9B,YAAM,WAAW,MAAM,KAAK,QAAQ,aAAa,IAAI,CAAC;AAGtD,YAAM,QAAS,KAAsD,MAAM;AAC3E,UAAI,SAAS,QAAQ,SAAS,KAAK,MAAO,OAAM,OAAO,cAAc,SAAS,OAAO;AACrF,aAAO,SAAS;AAAA,IAClB,GAAG;AACH,WAAO,KAAK,QAAQ;AAAA,EACtB,CAAC;AAED,MAAI,QAAQ,aAAa,OAAO,KAAK,UAAU;AAC7C;AAAC,IAAC,IAAqD,MAAM,IAAI;AAAA,EACnE,CAAC;AAED,MAAI,SAAS,kBAAkB,eAAgB,SAAyB,OAAoC;AAC1G,QAAK,MAAM,QAAQ,OAAO,MAAO,MAAM;AACrC,YAAM,MAAM,KAAK,GAAG,EAAE,OAAO,oBAAoB,MAAM,EAAE,KAAK,EAAE,OAAO,kBAAkB,CAAC;AAAA,IAC5F;AAAA,EACF,CAAC;AAED,QAAM,QAAQ,OAAO,KAAqB,UAAwB;AAChE,UAAM,MAAM,MAAM,KAAK,QAAQ,aAAa,GAAG,CAAC;AAChD,UAAM,KAAK,IAAI,MAAM;AACrB,QAAI,QAAQ,QAAQ,CAAC,OAAO,SAAS;AACnC,UAAI,SAAS,aAAc,OAAM,OAAO,MAAM,KAAK;AAAA,IACrD,CAAC;AACD,UAAM,UAAU,IAAI,QAAQ,aAAa;AACzC,QAAI,QAAQ,SAAS,EAAG,OAAM,OAAO,cAAc,OAAO;AAC1D,WAAO,MAAM,KAAK,IAAI,SAAS,OAAO,OAAO,OAAO,KAAK,MAAM,IAAI,YAAY,CAAC,CAAC;AAAA,EACnF;AACA,MAAI,MAAM,EAAE,QAAQ,CAAC,OAAO,MAAM,GAAG,KAAK,GAAG,IAAI,MAAM,SAAS,MAAM,CAAC;AACzE;AAKE,OAA8C,uBAAO,IAAI,eAAe,CAAC,IAAI;AAC7E,OAA8C,uBAAO,IAAI,sBAAsB,CAAC,IAAI;AAE/E,IAAM,gBAAgB;AAC7B,IAAO,kBAAQ;","names":[]}
package/dist/fastify.mjs CHANGED
@@ -8,7 +8,9 @@ function toWebRequest(req) {
8
8
  if (Array.isArray(v)) for (const one of v) headers.append(k, one);
9
9
  else if (v !== void 0) headers.set(k, v);
10
10
  }
11
- return new Request(new URL(req.url, originOf(req)), { method: req.method, headers });
11
+ headers.set("x-forwarded-for", req.ip);
12
+ const body = req.method === "GET" || req.method === "HEAD" || req.body === void 0 || req.body === null ? void 0 : typeof req.body === "string" ? req.body : JSON.stringify(req.body);
13
+ return new Request(new URL(req.url, originOf(req)), { method: req.method, headers, body });
12
14
  }
13
15
  var kSession = /* @__PURE__ */ Symbol("cauthy.session");
14
16
  var kReply = /* @__PURE__ */ Symbol("cauthy.reply");
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/fastify.ts"],"sourcesContent":["// Fastify: the routes, and who is signed in on every request.\n//\n// await app.register(cauthyFastify, { auth })\n//\n// app.get('/api/me', async (req, reply) => {\n// const session = await req.cauthy()\n// if (!session) return reply.code(401).send({ error: 'unauthenticated' })\n// return session.user\n// })\n//\n// app.get('/api/books', { preHandler: app.requireSession }, async (req) => { … })\n//\n// Here a session that needs renewing is renewed on the spot: Fastify has the\n// reply in hand, so the new cookie always goes back.\n\nimport type { FastifyInstance, FastifyPluginAsync, FastifyReply, FastifyRequest } from 'fastify'\nimport type { Cauthy } from './cauthy'\nimport type { Session } from './types'\n\ndeclare module 'fastify' {\n interface FastifyRequest {\n /** Who is signed in, or null. Asked once per request. */\n cauthy(): Promise<Session | null>\n }\n interface FastifyInstance {\n /** A preHandler that answers 401 unless somebody is signed in. */\n requireSession(request: FastifyRequest, reply: FastifyReply): Promise<void>\n }\n}\n\nexport interface CauthyFastifyOptions {\n auth: Cauthy\n}\n\nfunction originOf(req: FastifyRequest): string {\n return `${req.protocol}://${req.headers.host ?? 'localhost'}`\n}\n\nfunction toWebRequest(req: FastifyRequest): Request {\n const headers = new Headers()\n for (const [k, v] of Object.entries(req.headers)) {\n if (Array.isArray(v)) for (const one of v) headers.append(k, one)\n else if (v !== undefined) headers.set(k, v)\n }\n // The routes read no body: what they need is in the URL and the cookies.\n return new Request(new URL(req.url, originOf(req)), { method: req.method, headers })\n}\n\nconst kSession = Symbol('cauthy.session')\nconst kReply = Symbol('cauthy.reply')\n\nconst plugin: FastifyPluginAsync<CauthyFastifyOptions> = async (app: FastifyInstance, { auth }) => {\n const base = auth.options.basePath\n\n app.decorateRequest('cauthy', async function (this: FastifyRequest): Promise<Session | null> {\n const self = this as FastifyRequest & { [kSession]?: Promise<Session | null> }\n self[kSession] ??= (async () => {\n const resolved = await auth.resolve(toWebRequest(this))\n // Set through the raw response so the cookie leaves whatever the route\n // answers with, even an error.\n const reply = (this as FastifyRequest & { [kReply]?: FastifyReply })[kReply]\n if (resolved.cookies.length > 0 && reply) reply.header('set-cookie', resolved.cookies)\n return resolved.session\n })()\n return self[kSession]\n })\n\n app.addHook('onRequest', async (req, reply) => {\n ;(req as FastifyRequest & { [kReply]?: FastifyReply })[kReply] = reply\n })\n\n app.decorate('requireSession', async function (request: FastifyRequest, reply: FastifyReply): Promise<void> {\n if ((await request.cauthy()) === null) {\n await reply.code(401).header('x-cauthy-session', 'none').send({ error: 'unauthenticated' })\n }\n })\n\n const serve = async (req: FastifyRequest, reply: FastifyReply) => {\n const res = await auth.handler(toWebRequest(req))\n reply.code(res.status)\n res.headers.forEach((value, name) => {\n if (name !== 'set-cookie') reply.header(name, value)\n })\n const cookies = res.headers.getSetCookie()\n if (cookies.length > 0) reply.header('set-cookie', cookies)\n return reply.send(res.body === null ? null : Buffer.from(await res.arrayBuffer()))\n }\n app.route({ method: ['GET', 'POST'], url: `${base}/*`, handler: serve })\n}\n\n\n// Outside encapsulation: `req.cauthy()` and `requireSession` are for the whole\n// application, not only for routes registered beside this plugin.\n;(plugin as unknown as Record<symbol, boolean>)[Symbol.for('skip-override')] = true\n;(plugin as unknown as Record<symbol, unknown>)[Symbol.for('fastify.display-name')] = 'cauthy-auth'\n\nexport const cauthyFastify = plugin\nexport default plugin\n"],"mappings":";AAkCA,SAAS,SAAS,KAA6B;AAC7C,SAAO,GAAG,IAAI,QAAQ,MAAM,IAAI,QAAQ,QAAQ,WAAW;AAC7D;AAEA,SAAS,aAAa,KAA8B;AAClD,QAAM,UAAU,IAAI,QAAQ;AAC5B,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,IAAI,OAAO,GAAG;AAChD,QAAI,MAAM,QAAQ,CAAC,EAAG,YAAW,OAAO,EAAG,SAAQ,OAAO,GAAG,GAAG;AAAA,aACvD,MAAM,OAAW,SAAQ,IAAI,GAAG,CAAC;AAAA,EAC5C;AAEA,SAAO,IAAI,QAAQ,IAAI,IAAI,IAAI,KAAK,SAAS,GAAG,CAAC,GAAG,EAAE,QAAQ,IAAI,QAAQ,QAAQ,CAAC;AACrF;AAEA,IAAM,WAAW,uBAAO,gBAAgB;AACxC,IAAM,SAAS,uBAAO,cAAc;AAEpC,IAAM,SAAmD,OAAO,KAAsB,EAAE,KAAK,MAAM;AACjG,QAAM,OAAO,KAAK,QAAQ;AAE1B,MAAI,gBAAgB,UAAU,iBAA+D;AAC3F,UAAM,OAAO;AACb,SAAK,QAAQ,OAAO,YAAY;AAC9B,YAAM,WAAW,MAAM,KAAK,QAAQ,aAAa,IAAI,CAAC;AAGtD,YAAM,QAAS,KAAsD,MAAM;AAC3E,UAAI,SAAS,QAAQ,SAAS,KAAK,MAAO,OAAM,OAAO,cAAc,SAAS,OAAO;AACrF,aAAO,SAAS;AAAA,IAClB,GAAG;AACH,WAAO,KAAK,QAAQ;AAAA,EACtB,CAAC;AAED,MAAI,QAAQ,aAAa,OAAO,KAAK,UAAU;AAC7C;AAAC,IAAC,IAAqD,MAAM,IAAI;AAAA,EACnE,CAAC;AAED,MAAI,SAAS,kBAAkB,eAAgB,SAAyB,OAAoC;AAC1G,QAAK,MAAM,QAAQ,OAAO,MAAO,MAAM;AACrC,YAAM,MAAM,KAAK,GAAG,EAAE,OAAO,oBAAoB,MAAM,EAAE,KAAK,EAAE,OAAO,kBAAkB,CAAC;AAAA,IAC5F;AAAA,EACF,CAAC;AAED,QAAM,QAAQ,OAAO,KAAqB,UAAwB;AAChE,UAAM,MAAM,MAAM,KAAK,QAAQ,aAAa,GAAG,CAAC;AAChD,UAAM,KAAK,IAAI,MAAM;AACrB,QAAI,QAAQ,QAAQ,CAAC,OAAO,SAAS;AACnC,UAAI,SAAS,aAAc,OAAM,OAAO,MAAM,KAAK;AAAA,IACrD,CAAC;AACD,UAAM,UAAU,IAAI,QAAQ,aAAa;AACzC,QAAI,QAAQ,SAAS,EAAG,OAAM,OAAO,cAAc,OAAO;AAC1D,WAAO,MAAM,KAAK,IAAI,SAAS,OAAO,OAAO,OAAO,KAAK,MAAM,IAAI,YAAY,CAAC,CAAC;AAAA,EACnF;AACA,MAAI,MAAM,EAAE,QAAQ,CAAC,OAAO,MAAM,GAAG,KAAK,GAAG,IAAI,MAAM,SAAS,MAAM,CAAC;AACzE;AAKE,OAA8C,uBAAO,IAAI,eAAe,CAAC,IAAI;AAC7E,OAA8C,uBAAO,IAAI,sBAAsB,CAAC,IAAI;AAE/E,IAAM,gBAAgB;AAC7B,IAAO,kBAAQ;","names":[]}
1
+ {"version":3,"sources":["../src/fastify.ts"],"sourcesContent":["// Fastify: the routes, and who is signed in on every request.\n//\n// await app.register(cauthyFastify, { auth })\n//\n// app.get('/api/me', async (req, reply) => {\n// const session = await req.cauthy()\n// if (!session) return reply.code(401).send({ error: 'unauthenticated' })\n// return session.user\n// })\n//\n// app.get('/api/books', { preHandler: app.requireSession }, async (req) => { … })\n//\n// Here a session that needs renewing is renewed on the spot: Fastify has the\n// reply in hand, so the new cookie always goes back.\n\nimport type { FastifyInstance, FastifyPluginAsync, FastifyReply, FastifyRequest } from 'fastify'\nimport type { Cauthy } from './cauthy'\nimport type { Session } from './types'\n\ndeclare module 'fastify' {\n interface FastifyRequest {\n /** Who is signed in, or null. Asked once per request. */\n cauthy(): Promise<Session | null>\n }\n interface FastifyInstance {\n /** A preHandler that answers 401 unless somebody is signed in. */\n requireSession(request: FastifyRequest, reply: FastifyReply): Promise<void>\n }\n}\n\nexport interface CauthyFastifyOptions {\n auth: Cauthy\n}\n\nfunction originOf(req: FastifyRequest): string {\n return `${req.protocol}://${req.headers.host ?? 'localhost'}`\n}\n\nfunction toWebRequest(req: FastifyRequest): Request {\n const headers = new Headers()\n for (const [k, v] of Object.entries(req.headers)) {\n if (Array.isArray(v)) for (const one of v) headers.append(k, one)\n else if (v !== undefined) headers.set(k, v)\n }\n // Fastify knows who is calling (it applies `trustProxy`): that address is\n // the one passed on to Cauthy, whatever the header claimed.\n headers.set('x-forwarded-for', req.ip)\n // What Fastify parsed is the body: the application's own sign-in screens post JSON.\n const body = req.method === 'GET' || req.method === 'HEAD' || req.body === undefined || req.body === null\n ? undefined\n : typeof req.body === 'string' ? req.body : JSON.stringify(req.body)\n return new Request(new URL(req.url, originOf(req)), { method: req.method, headers, body })\n}\n\nconst kSession = Symbol('cauthy.session')\nconst kReply = Symbol('cauthy.reply')\n\nconst plugin: FastifyPluginAsync<CauthyFastifyOptions> = async (app: FastifyInstance, { auth }) => {\n const base = auth.options.basePath\n\n app.decorateRequest('cauthy', async function (this: FastifyRequest): Promise<Session | null> {\n const self = this as FastifyRequest & { [kSession]?: Promise<Session | null> }\n self[kSession] ??= (async () => {\n const resolved = await auth.resolve(toWebRequest(this))\n // Set through the raw response so the cookie leaves whatever the route\n // answers with, even an error.\n const reply = (this as FastifyRequest & { [kReply]?: FastifyReply })[kReply]\n if (resolved.cookies.length > 0 && reply) reply.header('set-cookie', resolved.cookies)\n return resolved.session\n })()\n return self[kSession]\n })\n\n app.addHook('onRequest', async (req, reply) => {\n ;(req as FastifyRequest & { [kReply]?: FastifyReply })[kReply] = reply\n })\n\n app.decorate('requireSession', async function (request: FastifyRequest, reply: FastifyReply): Promise<void> {\n if ((await request.cauthy()) === null) {\n await reply.code(401).header('x-cauthy-session', 'none').send({ error: 'unauthenticated' })\n }\n })\n\n const serve = async (req: FastifyRequest, reply: FastifyReply) => {\n const res = await auth.handler(toWebRequest(req))\n reply.code(res.status)\n res.headers.forEach((value, name) => {\n if (name !== 'set-cookie') reply.header(name, value)\n })\n const cookies = res.headers.getSetCookie()\n if (cookies.length > 0) reply.header('set-cookie', cookies)\n return reply.send(res.body === null ? null : Buffer.from(await res.arrayBuffer()))\n }\n app.route({ method: ['GET', 'POST'], url: `${base}/*`, handler: serve })\n}\n\n\n// Outside encapsulation: `req.cauthy()` and `requireSession` are for the whole\n// application, not only for routes registered beside this plugin.\n;(plugin as unknown as Record<symbol, boolean>)[Symbol.for('skip-override')] = true\n;(plugin as unknown as Record<symbol, unknown>)[Symbol.for('fastify.display-name')] = 'cauthy-auth'\n\nexport const cauthyFastify = plugin\nexport default plugin\n"],"mappings":";AAkCA,SAAS,SAAS,KAA6B;AAC7C,SAAO,GAAG,IAAI,QAAQ,MAAM,IAAI,QAAQ,QAAQ,WAAW;AAC7D;AAEA,SAAS,aAAa,KAA8B;AAClD,QAAM,UAAU,IAAI,QAAQ;AAC5B,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,IAAI,OAAO,GAAG;AAChD,QAAI,MAAM,QAAQ,CAAC,EAAG,YAAW,OAAO,EAAG,SAAQ,OAAO,GAAG,GAAG;AAAA,aACvD,MAAM,OAAW,SAAQ,IAAI,GAAG,CAAC;AAAA,EAC5C;AAGA,UAAQ,IAAI,mBAAmB,IAAI,EAAE;AAErC,QAAM,OAAO,IAAI,WAAW,SAAS,IAAI,WAAW,UAAU,IAAI,SAAS,UAAa,IAAI,SAAS,OACjG,SACA,OAAO,IAAI,SAAS,WAAW,IAAI,OAAO,KAAK,UAAU,IAAI,IAAI;AACrE,SAAO,IAAI,QAAQ,IAAI,IAAI,IAAI,KAAK,SAAS,GAAG,CAAC,GAAG,EAAE,QAAQ,IAAI,QAAQ,SAAS,KAAK,CAAC;AAC3F;AAEA,IAAM,WAAW,uBAAO,gBAAgB;AACxC,IAAM,SAAS,uBAAO,cAAc;AAEpC,IAAM,SAAmD,OAAO,KAAsB,EAAE,KAAK,MAAM;AACjG,QAAM,OAAO,KAAK,QAAQ;AAE1B,MAAI,gBAAgB,UAAU,iBAA+D;AAC3F,UAAM,OAAO;AACb,SAAK,QAAQ,OAAO,YAAY;AAC9B,YAAM,WAAW,MAAM,KAAK,QAAQ,aAAa,IAAI,CAAC;AAGtD,YAAM,QAAS,KAAsD,MAAM;AAC3E,UAAI,SAAS,QAAQ,SAAS,KAAK,MAAO,OAAM,OAAO,cAAc,SAAS,OAAO;AACrF,aAAO,SAAS;AAAA,IAClB,GAAG;AACH,WAAO,KAAK,QAAQ;AAAA,EACtB,CAAC;AAED,MAAI,QAAQ,aAAa,OAAO,KAAK,UAAU;AAC7C;AAAC,IAAC,IAAqD,MAAM,IAAI;AAAA,EACnE,CAAC;AAED,MAAI,SAAS,kBAAkB,eAAgB,SAAyB,OAAoC;AAC1G,QAAK,MAAM,QAAQ,OAAO,MAAO,MAAM;AACrC,YAAM,MAAM,KAAK,GAAG,EAAE,OAAO,oBAAoB,MAAM,EAAE,KAAK,EAAE,OAAO,kBAAkB,CAAC;AAAA,IAC5F;AAAA,EACF,CAAC;AAED,QAAM,QAAQ,OAAO,KAAqB,UAAwB;AAChE,UAAM,MAAM,MAAM,KAAK,QAAQ,aAAa,GAAG,CAAC;AAChD,UAAM,KAAK,IAAI,MAAM;AACrB,QAAI,QAAQ,QAAQ,CAAC,OAAO,SAAS;AACnC,UAAI,SAAS,aAAc,OAAM,OAAO,MAAM,KAAK;AAAA,IACrD,CAAC;AACD,UAAM,UAAU,IAAI,QAAQ,aAAa;AACzC,QAAI,QAAQ,SAAS,EAAG,OAAM,OAAO,cAAc,OAAO;AAC1D,WAAO,MAAM,KAAK,IAAI,SAAS,OAAO,OAAO,OAAO,KAAK,MAAM,IAAI,YAAY,CAAC,CAAC;AAAA,EACnF;AACA,MAAI,MAAM,EAAE,QAAQ,CAAC,OAAO,MAAM,GAAG,KAAK,GAAG,IAAI,MAAM,SAAS,MAAM,CAAC;AACzE;AAKE,OAA8C,uBAAO,IAAI,eAAe,CAAC,IAAI;AAC7E,OAA8C,uBAAO,IAAI,sBAAsB,CAAC,IAAI;AAE/E,IAAM,gBAAgB;AAC7B,IAAO,kBAAQ;","names":[]}
@@ -0,0 +1,23 @@
1
+ import { MiddlewareHandler } from 'hono';
2
+ import { C as Cauthy } from './cauthy-C29HCvag.mjs';
3
+ import { S as Session } from './system-ZD_Wa8Bm.mjs';
4
+ import 'jose';
5
+ import './theme.mjs';
6
+
7
+ /** What the middleware keeps on the context: `new Hono<{ Variables: CauthyVariables }>()`. */
8
+ interface CauthyVariables {
9
+ /** Who is signed in, or null. */
10
+ session: Session | null;
11
+ }
12
+ type Env = {
13
+ Variables: CauthyVariables;
14
+ };
15
+ /**
16
+ * Serves the routes under the handler's `basePath`, and sets `session` for
17
+ * every other request. Mount it once, before the routes that use it.
18
+ */
19
+ declare function cauthyHono(auth: Cauthy): MiddlewareHandler<Env>;
20
+ /** For a route only a signed-in person may call: answers 401 otherwise. Needs `cauthyHono` mounted before it. */
21
+ declare const requireSession: MiddlewareHandler<Env>;
22
+
23
+ export { type CauthyVariables, cauthyHono, requireSession };
package/dist/hono.d.ts ADDED
@@ -0,0 +1,23 @@
1
+ import { MiddlewareHandler } from 'hono';
2
+ import { C as Cauthy } from './cauthy-Bn3iv50y.js';
3
+ import { S as Session } from './system-DhRr_WxR.js';
4
+ import 'jose';
5
+ import './theme.js';
6
+
7
+ /** What the middleware keeps on the context: `new Hono<{ Variables: CauthyVariables }>()`. */
8
+ interface CauthyVariables {
9
+ /** Who is signed in, or null. */
10
+ session: Session | null;
11
+ }
12
+ type Env = {
13
+ Variables: CauthyVariables;
14
+ };
15
+ /**
16
+ * Serves the routes under the handler's `basePath`, and sets `session` for
17
+ * every other request. Mount it once, before the routes that use it.
18
+ */
19
+ declare function cauthyHono(auth: Cauthy): MiddlewareHandler<Env>;
20
+ /** For a route only a signed-in person may call: answers 401 otherwise. Needs `cauthyHono` mounted before it. */
21
+ declare const requireSession: MiddlewareHandler<Env>;
22
+
23
+ export { type CauthyVariables, cauthyHono, requireSession };
package/dist/hono.js ADDED
@@ -0,0 +1,50 @@
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
+
20
+ // src/hono.ts
21
+ var hono_exports = {};
22
+ __export(hono_exports, {
23
+ cauthyHono: () => cauthyHono,
24
+ requireSession: () => requireSession
25
+ });
26
+ module.exports = __toCommonJS(hono_exports);
27
+ function cauthyHono(auth) {
28
+ const base = auth.options.basePath;
29
+ return async (c, next) => {
30
+ const path = new URL(c.req.url).pathname;
31
+ if (path === base || path.startsWith(`${base}/`)) return auth.handler(c.req.raw);
32
+ const resolved = await auth.resolve(c.req.raw);
33
+ c.set("session", resolved.session);
34
+ await next();
35
+ for (const cookie of resolved.cookies) c.header("set-cookie", cookie, { append: true });
36
+ };
37
+ }
38
+ var requireSession = async (c, next) => {
39
+ if (c.get("session") === null || c.get("session") === void 0) {
40
+ c.header("x-cauthy-session", "none");
41
+ return c.json({ error: "unauthenticated" }, 401);
42
+ }
43
+ await next();
44
+ };
45
+ // Annotate the CommonJS export names for ESM import in node:
46
+ 0 && (module.exports = {
47
+ cauthyHono,
48
+ requireSession
49
+ });
50
+ //# sourceMappingURL=hono.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hono.ts"],"sourcesContent":["// Hono: the routes, and who is signed in on every request.\n//\n// const app = new Hono<{ Variables: CauthyVariables }>()\n// app.use(cauthyHono(auth))\n//\n// app.get('/api/me', (c) => {\n// const session = c.get('session')\n// return session ? c.json(session.user) : c.json({ error: 'unauthenticated' }, 401)\n// })\n//\n// app.get('/api/books', requireSession, (c) => { … })\n//\n// A session that needs renewing is renewed on the spot, and its new cookie\n// leaves with whatever the route answers. It runs wherever Hono does.\n\nimport type { MiddlewareHandler } from 'hono'\nimport type { Cauthy } from './cauthy'\nimport type { Session } from './types'\n\n/** What the middleware keeps on the context: `new Hono<{ Variables: CauthyVariables }>()`. */\nexport interface CauthyVariables {\n /** Who is signed in, or null. */\n session: Session | null\n}\n\ntype Env = { Variables: CauthyVariables }\n\n/**\n * Serves the routes under the handler's `basePath`, and sets `session` for\n * every other request. Mount it once, before the routes that use it.\n */\nexport function cauthyHono(auth: Cauthy): MiddlewareHandler<Env> {\n const base = auth.options.basePath\n return async (c, next) => {\n const path = new URL(c.req.url).pathname\n if (path === base || path.startsWith(`${base}/`)) return auth.handler(c.req.raw)\n\n const resolved = await auth.resolve(c.req.raw)\n c.set('session', resolved.session)\n await next()\n for (const cookie of resolved.cookies) c.header('set-cookie', cookie, { append: true })\n }\n}\n\n/** For a route only a signed-in person may call: answers 401 otherwise. Needs `cauthyHono` mounted before it. */\nexport const requireSession: MiddlewareHandler<Env> = async (c, next) => {\n if (c.get('session') === null || c.get('session') === undefined) {\n c.header('x-cauthy-session', 'none')\n return c.json({ error: 'unauthenticated' }, 401)\n }\n await next()\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA+BO,SAAS,WAAW,MAAsC;AAC/D,QAAM,OAAO,KAAK,QAAQ;AAC1B,SAAO,OAAO,GAAG,SAAS;AACxB,UAAM,OAAO,IAAI,IAAI,EAAE,IAAI,GAAG,EAAE;AAChC,QAAI,SAAS,QAAQ,KAAK,WAAW,GAAG,IAAI,GAAG,EAAG,QAAO,KAAK,QAAQ,EAAE,IAAI,GAAG;AAE/E,UAAM,WAAW,MAAM,KAAK,QAAQ,EAAE,IAAI,GAAG;AAC7C,MAAE,IAAI,WAAW,SAAS,OAAO;AACjC,UAAM,KAAK;AACX,eAAW,UAAU,SAAS,QAAS,GAAE,OAAO,cAAc,QAAQ,EAAE,QAAQ,KAAK,CAAC;AAAA,EACxF;AACF;AAGO,IAAM,iBAAyC,OAAO,GAAG,SAAS;AACvE,MAAI,EAAE,IAAI,SAAS,MAAM,QAAQ,EAAE,IAAI,SAAS,MAAM,QAAW;AAC/D,MAAE,OAAO,oBAAoB,MAAM;AACnC,WAAO,EAAE,KAAK,EAAE,OAAO,kBAAkB,GAAG,GAAG;AAAA,EACjD;AACA,QAAM,KAAK;AACb;","names":[]}
package/dist/hono.mjs ADDED
@@ -0,0 +1,24 @@
1
+ // src/hono.ts
2
+ function cauthyHono(auth) {
3
+ const base = auth.options.basePath;
4
+ return async (c, next) => {
5
+ const path = new URL(c.req.url).pathname;
6
+ if (path === base || path.startsWith(`${base}/`)) return auth.handler(c.req.raw);
7
+ const resolved = await auth.resolve(c.req.raw);
8
+ c.set("session", resolved.session);
9
+ await next();
10
+ for (const cookie of resolved.cookies) c.header("set-cookie", cookie, { append: true });
11
+ };
12
+ }
13
+ var requireSession = async (c, next) => {
14
+ if (c.get("session") === null || c.get("session") === void 0) {
15
+ c.header("x-cauthy-session", "none");
16
+ return c.json({ error: "unauthenticated" }, 401);
17
+ }
18
+ await next();
19
+ };
20
+ export {
21
+ cauthyHono,
22
+ requireSession
23
+ };
24
+ //# sourceMappingURL=hono.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hono.ts"],"sourcesContent":["// Hono: the routes, and who is signed in on every request.\n//\n// const app = new Hono<{ Variables: CauthyVariables }>()\n// app.use(cauthyHono(auth))\n//\n// app.get('/api/me', (c) => {\n// const session = c.get('session')\n// return session ? c.json(session.user) : c.json({ error: 'unauthenticated' }, 401)\n// })\n//\n// app.get('/api/books', requireSession, (c) => { … })\n//\n// A session that needs renewing is renewed on the spot, and its new cookie\n// leaves with whatever the route answers. It runs wherever Hono does.\n\nimport type { MiddlewareHandler } from 'hono'\nimport type { Cauthy } from './cauthy'\nimport type { Session } from './types'\n\n/** What the middleware keeps on the context: `new Hono<{ Variables: CauthyVariables }>()`. */\nexport interface CauthyVariables {\n /** Who is signed in, or null. */\n session: Session | null\n}\n\ntype Env = { Variables: CauthyVariables }\n\n/**\n * Serves the routes under the handler's `basePath`, and sets `session` for\n * every other request. Mount it once, before the routes that use it.\n */\nexport function cauthyHono(auth: Cauthy): MiddlewareHandler<Env> {\n const base = auth.options.basePath\n return async (c, next) => {\n const path = new URL(c.req.url).pathname\n if (path === base || path.startsWith(`${base}/`)) return auth.handler(c.req.raw)\n\n const resolved = await auth.resolve(c.req.raw)\n c.set('session', resolved.session)\n await next()\n for (const cookie of resolved.cookies) c.header('set-cookie', cookie, { append: true })\n }\n}\n\n/** For a route only a signed-in person may call: answers 401 otherwise. Needs `cauthyHono` mounted before it. */\nexport const requireSession: MiddlewareHandler<Env> = async (c, next) => {\n if (c.get('session') === null || c.get('session') === undefined) {\n c.header('x-cauthy-session', 'none')\n return c.json({ error: 'unauthenticated' }, 401)\n }\n await next()\n}\n"],"mappings":";AA+BO,SAAS,WAAW,MAAsC;AAC/D,QAAM,OAAO,KAAK,QAAQ;AAC1B,SAAO,OAAO,GAAG,SAAS;AACxB,UAAM,OAAO,IAAI,IAAI,EAAE,IAAI,GAAG,EAAE;AAChC,QAAI,SAAS,QAAQ,KAAK,WAAW,GAAG,IAAI,GAAG,EAAG,QAAO,KAAK,QAAQ,EAAE,IAAI,GAAG;AAE/E,UAAM,WAAW,MAAM,KAAK,QAAQ,EAAE,IAAI,GAAG;AAC7C,MAAE,IAAI,WAAW,SAAS,OAAO;AACjC,UAAM,KAAK;AACX,eAAW,UAAU,SAAS,QAAS,GAAE,OAAO,cAAc,QAAQ,EAAE,QAAQ,KAAK,CAAC;AAAA,EACxF;AACF;AAGO,IAAM,iBAAyC,OAAO,GAAG,SAAS;AACvE,MAAI,EAAE,IAAI,SAAS,MAAM,QAAQ,EAAE,IAAI,SAAS,MAAM,QAAW;AAC/D,MAAE,OAAO,oBAAoB,MAAM;AACnC,WAAO,EAAE,KAAK,EAAE,OAAO,kBAAkB,GAAG,GAAG;AAAA,EACjD;AACA,QAAM,KAAK;AACb;","names":[]}
package/dist/index.d.mts CHANGED
@@ -1,8 +1,8 @@
1
- export { C as Cauthy, a as CauthyEvent, b as CauthyWebhookError, R as Resolved, V as VerifyWebhookOptions, c as createCauthy, v as verifyWebhook } from './cauthy-hswMoS7B.mjs';
2
- export { C as CauthyApiError, a as CauthyConfigError, b as CauthyOptions, c as CauthySystem, J as JsonValue, N as NewMember, O as Organization, d as OrganizationMember, P as PublicSession, S as Session, e as SessionOrganization, f as SessionStatus, g as SessionUser, h as SystemKey, i as SystemOptions, j as createSystem } from './system-CR8p4BjB.mjs';
3
- export { CauthyTheme, ImportedTheme, PushThemeOptions, StackmythThemeOptions, ThemeFont, ThemeTexts, pushTheme, themeFromStackmyth } from './theme.mjs';
4
- export { P as Permitted, a as PolicyPermission, b as PolicyRole, c as PushPolicyOptions, d as can, p as pushPolicy } from './permissions-B-a3eN0h.mjs';
5
- import 'jose';
1
+ export { C as Cauthy, a as CauthyEvent, b as CauthyWebhookError, R as Resolved, V as VerifyWebhookOptions, c as createCauthy, v as verifyWebhook } from './cauthy-C29HCvag.mjs';
2
+ export { C as CauthyApiError, a as CauthyConfigError, b as CauthyOptions, c as CauthySystem, J as JsonValue, N as NewMember, O as Organization, d as OrganizationMember, P as PermissionOf, e as Permitted, f as Policy, g as PolicyPermission, h as PolicyRole, i as PublicSession, j as PushPolicyOptions, R as RoleOf, S as Session, k as SessionOrganization, l as SessionStatus, m as SessionUser, n as SystemKey, o as SystemOptions, p as can, q as createSystem, r as definePolicy, s as policySource, t as pullPolicy, u as pushPolicy } from './system-ZD_Wa8Bm.mjs';
3
+ export { CauthyTheme, ImportedTheme, PushThemeOptions, StackmythThemeOptions, StackmythTokens, ThemeFont, ThemeTexts, pushTheme, themeFromStackmyth, tokensFromStackmyth } from './theme.mjs';
4
+ export { A as AuthField, F as FieldProblem, M as MIN_PASSWORD, c as checkCode, a as checkEmail, b as checkName, d as checkNewPassword, e as checkPassword } from './validate-B_iC-4y8.mjs';
5
+ import { JWTVerifyGetKey } from 'jose';
6
6
 
7
7
  interface ConnectOptions {
8
8
  /** The system's name, as its organizations are filed under: lowercase, digits, - or _. */
@@ -46,4 +46,42 @@ interface Connected {
46
46
  }
47
47
  declare function connectSystem(o: ConnectOptions): Promise<Connected>;
48
48
 
49
- export { type ConnectOptions, type Connected, connectSystem };
49
+ /** Who a verified access token belongs to. */
50
+ interface TokenIdentity {
51
+ /** The person. For a system's own token, the client it identifies as. */
52
+ userId: string;
53
+ tenantId: string;
54
+ email?: string;
55
+ roles: string[];
56
+ /** Set when the token is a system's own and not a person's. */
57
+ system?: string;
58
+ /** UTC, ISO 8601. */
59
+ expiresAt: string;
60
+ /** The token as it arrived, to pass on. */
61
+ token: string;
62
+ }
63
+ declare class CauthyTokenError extends Error {
64
+ readonly reason: string;
65
+ constructor(reason: string);
66
+ }
67
+ interface VerifyTokenOptions {
68
+ /** Cauthy's address. Default: `CAUTHY_ISSUER`. */
69
+ issuer?: string;
70
+ /** The audience the tokens must carry. Default: `CAUTHY_AUDIENCE`; unchecked when neither is set. */
71
+ audience?: string;
72
+ /** Refuse a token of any other workspace. Default: `CAUTHY_TENANT_ID`; unchecked when neither is set. */
73
+ tenantId?: string;
74
+ /** Cauthy's keys. Default: fetched from the issuer and cached. */
75
+ jwks?: JWTVerifyGetKey;
76
+ /** The moment to verify at. Default: now. */
77
+ now?: Date;
78
+ }
79
+ /**
80
+ * Verifies an access token (or the `Authorization: Bearer` of a request) and
81
+ * answers who it belongs to. Checked: the signature, against Cauthy's
82
+ * published keys; that Cauthy issued it; that it has not expired; and the
83
+ * audience and the workspace, when given.
84
+ */
85
+ declare function verifyToken(from: string | Request | Headers, options?: VerifyTokenOptions): Promise<TokenIdentity>;
86
+
87
+ export { CauthyTokenError, type ConnectOptions, type Connected, type TokenIdentity, type VerifyTokenOptions, connectSystem, verifyToken };
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- export { C as Cauthy, a as CauthyEvent, b as CauthyWebhookError, R as Resolved, V as VerifyWebhookOptions, c as createCauthy, v as verifyWebhook } from './cauthy-BCTCqubt.js';
2
- export { C as CauthyApiError, a as CauthyConfigError, b as CauthyOptions, c as CauthySystem, J as JsonValue, N as NewMember, O as Organization, d as OrganizationMember, P as PublicSession, S as Session, e as SessionOrganization, f as SessionStatus, g as SessionUser, h as SystemKey, i as SystemOptions, j as createSystem } from './system-DvcQjORr.js';
3
- export { CauthyTheme, ImportedTheme, PushThemeOptions, StackmythThemeOptions, ThemeFont, ThemeTexts, pushTheme, themeFromStackmyth } from './theme.js';
4
- export { P as Permitted, a as PolicyPermission, b as PolicyRole, c as PushPolicyOptions, d as can, p as pushPolicy } from './permissions-B-a3eN0h.js';
5
- import 'jose';
1
+ export { C as Cauthy, a as CauthyEvent, b as CauthyWebhookError, R as Resolved, V as VerifyWebhookOptions, c as createCauthy, v as verifyWebhook } from './cauthy-Bn3iv50y.js';
2
+ export { C as CauthyApiError, a as CauthyConfigError, b as CauthyOptions, c as CauthySystem, J as JsonValue, N as NewMember, O as Organization, d as OrganizationMember, P as PermissionOf, e as Permitted, f as Policy, g as PolicyPermission, h as PolicyRole, i as PublicSession, j as PushPolicyOptions, R as RoleOf, S as Session, k as SessionOrganization, l as SessionStatus, m as SessionUser, n as SystemKey, o as SystemOptions, p as can, q as createSystem, r as definePolicy, s as policySource, t as pullPolicy, u as pushPolicy } from './system-DhRr_WxR.js';
3
+ export { CauthyTheme, ImportedTheme, PushThemeOptions, StackmythThemeOptions, StackmythTokens, ThemeFont, ThemeTexts, pushTheme, themeFromStackmyth, tokensFromStackmyth } from './theme.js';
4
+ export { A as AuthField, F as FieldProblem, M as MIN_PASSWORD, c as checkCode, a as checkEmail, b as checkName, d as checkNewPassword, e as checkPassword } from './validate-B_iC-4y8.js';
5
+ import { JWTVerifyGetKey } from 'jose';
6
6
 
7
7
  interface ConnectOptions {
8
8
  /** The system's name, as its organizations are filed under: lowercase, digits, - or _. */
@@ -46,4 +46,42 @@ interface Connected {
46
46
  }
47
47
  declare function connectSystem(o: ConnectOptions): Promise<Connected>;
48
48
 
49
- export { type ConnectOptions, type Connected, connectSystem };
49
+ /** Who a verified access token belongs to. */
50
+ interface TokenIdentity {
51
+ /** The person. For a system's own token, the client it identifies as. */
52
+ userId: string;
53
+ tenantId: string;
54
+ email?: string;
55
+ roles: string[];
56
+ /** Set when the token is a system's own and not a person's. */
57
+ system?: string;
58
+ /** UTC, ISO 8601. */
59
+ expiresAt: string;
60
+ /** The token as it arrived, to pass on. */
61
+ token: string;
62
+ }
63
+ declare class CauthyTokenError extends Error {
64
+ readonly reason: string;
65
+ constructor(reason: string);
66
+ }
67
+ interface VerifyTokenOptions {
68
+ /** Cauthy's address. Default: `CAUTHY_ISSUER`. */
69
+ issuer?: string;
70
+ /** The audience the tokens must carry. Default: `CAUTHY_AUDIENCE`; unchecked when neither is set. */
71
+ audience?: string;
72
+ /** Refuse a token of any other workspace. Default: `CAUTHY_TENANT_ID`; unchecked when neither is set. */
73
+ tenantId?: string;
74
+ /** Cauthy's keys. Default: fetched from the issuer and cached. */
75
+ jwks?: JWTVerifyGetKey;
76
+ /** The moment to verify at. Default: now. */
77
+ now?: Date;
78
+ }
79
+ /**
80
+ * Verifies an access token (or the `Authorization: Bearer` of a request) and
81
+ * answers who it belongs to. Checked: the signature, against Cauthy's
82
+ * published keys; that Cauthy issued it; that it has not expired; and the
83
+ * audience and the workspace, when given.
84
+ */
85
+ declare function verifyToken(from: string | Request | Headers, options?: VerifyTokenOptions): Promise<TokenIdentity>;
86
+
87
+ export { CauthyTokenError, type ConnectOptions, type Connected, type TokenIdentity, type VerifyTokenOptions, connectSystem, verifyToken };