cauthy-auth 0.20.0 → 0.23.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 (43) hide show
  1. package/dist/{cauthy-Bn3iv50y.d.ts → cauthy-DGAy45G2.d.ts} +1 -1
  2. package/dist/{cauthy-C29HCvag.d.mts → cauthy-XkIbG5gE.d.mts} +1 -1
  3. package/dist/client.d.mts +133 -3
  4. package/dist/client.d.ts +133 -3
  5. package/dist/client.js +54 -0
  6. package/dist/client.js.map +1 -1
  7. package/dist/client.mjs +54 -0
  8. package/dist/client.mjs.map +1 -1
  9. package/dist/express.d.mts +2 -2
  10. package/dist/express.d.ts +2 -2
  11. package/dist/fastify.d.mts +2 -2
  12. package/dist/fastify.d.ts +2 -2
  13. package/dist/hono.d.mts +2 -2
  14. package/dist/hono.d.ts +2 -2
  15. package/dist/index.d.mts +2 -2
  16. package/dist/index.d.ts +2 -2
  17. package/dist/index.js +178 -5
  18. package/dist/index.js.map +1 -1
  19. package/dist/index.mjs +178 -5
  20. package/dist/index.mjs.map +1 -1
  21. package/dist/next.d.mts +2 -2
  22. package/dist/next.d.ts +2 -2
  23. package/dist/react.d.mts +171 -2
  24. package/dist/react.d.ts +171 -2
  25. package/dist/react.js +261 -3
  26. package/dist/react.js.map +1 -1
  27. package/dist/react.mjs +260 -3
  28. package/dist/react.mjs.map +1 -1
  29. package/dist/svelte.d.mts +2 -2
  30. package/dist/svelte.d.ts +2 -2
  31. package/dist/svelte.js +54 -0
  32. package/dist/svelte.js.map +1 -1
  33. package/dist/svelte.mjs +54 -0
  34. package/dist/svelte.mjs.map +1 -1
  35. package/dist/{system-ZD_Wa8Bm.d.mts → system-BxMsSIu1.d.mts} +2 -0
  36. package/dist/{system-DhRr_WxR.d.ts → system-DTIeDXDP.d.ts} +2 -0
  37. package/dist/vue.d.mts +2 -2
  38. package/dist/vue.d.ts +2 -2
  39. package/dist/vue.js +54 -0
  40. package/dist/vue.js.map +1 -1
  41. package/dist/vue.mjs +54 -0
  42. package/dist/vue.mjs.map +1 -1
  43. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -789,7 +789,8 @@ function createCauthy(given = {}) {
789
789
  emailVerified: b.email_verified === true,
790
790
  restricted: b.restricted === true,
791
791
  ...typeof b.email_verify_by === "string" ? { emailVerifyBy: b.email_verify_by } : {},
792
- ...typeof b.locale === "string" && b.locale !== "" ? { locale: b.locale } : {}
792
+ ...typeof b.locale === "string" && b.locale !== "" ? { locale: b.locale } : {},
793
+ ...b.anonymous === true ? { isAnonymous: true } : {}
793
794
  }
794
795
  };
795
796
  } catch {
@@ -998,6 +999,32 @@ function createCauthy(given = {}) {
998
999
  createdAt: String(d?.created_at ?? ""),
999
1000
  lastUsedAt: d?.last_used_at ? String(d.last_used_at) : null
1000
1001
  });
1002
+ const UUID = /^[0-9a-f-]{36}$/i;
1003
+ const seatOf = (d) => ({
1004
+ id: String(d?.id ?? ""),
1005
+ system: String(d?.system ?? ""),
1006
+ name: String(d?.name ?? ""),
1007
+ kind: String(d?.kind ?? ""),
1008
+ role: String(d?.role ?? ""),
1009
+ can: { readMembers: d?.can?.read_members === true, manageMembers: d?.can?.manage_members === true }
1010
+ });
1011
+ const orgMemberOf = (d) => ({
1012
+ userId: String(d?.user_id ?? ""),
1013
+ email: String(d?.email ?? ""),
1014
+ name: String(d?.name ?? ""),
1015
+ role: String(d?.role ?? ""),
1016
+ status: String(d?.status ?? ""),
1017
+ invited: d?.invited === true,
1018
+ manager: d?.manager === true,
1019
+ you: d?.you === true,
1020
+ since: String(d?.since ?? "")
1021
+ });
1022
+ const orgRoleOf = (d) => ({
1023
+ role: String(d?.role ?? ""),
1024
+ name: String(d?.name ?? ""),
1025
+ description: String(d?.description ?? ""),
1026
+ manager: d?.manager === true
1027
+ });
1001
1028
  const agentOf = (d) => ({
1002
1029
  id: String(d?.id ?? ""),
1003
1030
  name: String(d?.agent?.name ?? ""),
@@ -1116,6 +1143,9 @@ function createCauthy(given = {}) {
1116
1143
  "/me/mfa/phone/remove",
1117
1144
  "/sign-in/mfa/methods",
1118
1145
  "/sign-in/mfa/send",
1146
+ "/sign-in/mfa/push",
1147
+ "/sign-in/mfa/push/events",
1148
+ "/sign-in/mfa/push/finish",
1119
1149
  "/me/sessions",
1120
1150
  "/me/sessions/end",
1121
1151
  "/me/email",
@@ -1133,8 +1163,17 @@ function createCauthy(given = {}) {
1133
1163
  "/me/passkeys/add/finish",
1134
1164
  "/me/passkeys/remove",
1135
1165
  "/me/agents",
1136
- "/me/agents/disconnect"
1137
- ].includes(route) || route.startsWith("/sign-in/social/") || route.startsWith("/callback/") || route.startsWith("/me/identities/link/") || route === "/sign-in/sso" || route === "/sign-in/sso/discover" || route === "/sso/callback";
1166
+ "/me/agents/disconnect",
1167
+ "/sign-in/anonymous",
1168
+ "/me/upgrade",
1169
+ "/me/organizations",
1170
+ "/me/organizations/members",
1171
+ "/me/organizations/roles",
1172
+ "/me/organizations/members/add",
1173
+ "/me/organizations/members/role",
1174
+ "/me/organizations/members/remove",
1175
+ "/me/organizations/members/invite"
1176
+ ].includes(route) || route.startsWith("/sign-in/social/") || route.startsWith("/callback/") || route.startsWith("/me/identities/link/") || route.startsWith("/me/upgrade/social/") || route === "/sign-in/sso" || route === "/sign-in/sso/discover" || route === "/sso/callback";
1138
1177
  if (!own) return null;
1139
1178
  if (tenant === "") {
1140
1179
  return problem(500, "not_configured", "cauthy-auth: tenant (CAUTHY_TENANT) is required for the application's own sign-in screens");
@@ -1222,10 +1261,19 @@ function createCauthy(given = {}) {
1222
1261
  const clear = writeCookie(stepCookie, "", attrs(request, 0));
1223
1262
  const back = step?.returnTo ?? afterSignIn;
1224
1263
  const failedTo = (code2) => redirect(`${back}${back.includes("?") ? "&" : "?"}auth_error=${encodeURIComponent(code2)}`, [clear]);
1225
- if (step === null || step.kind !== "social" && step.kind !== "link" || step.provider !== provider || url.searchParams.get("state") !== step.token) return failedTo("state_mismatch");
1264
+ if (step === null || step.kind !== "social" && step.kind !== "link" && step.kind !== "upgrade" || step.provider !== provider || url.searchParams.get("state") !== step.token) return failedTo("state_mismatch");
1226
1265
  const code = url.searchParams.get("code");
1227
1266
  if (!code) return failedTo(url.searchParams.get("error") === "access_denied" ? "cancelled" : "provider_refused");
1228
1267
  const q = new URLSearchParams({ code, state: step.token, redirect_uri: `${originOf(request)}${basePath}/callback/${provider}` });
1268
+ if (step.kind === "upgrade") {
1269
+ const mine = await signedInAs(request);
1270
+ if ("response" in mine) return failedTo("unauthenticated");
1271
+ const done2 = await ask(request, "GET", `/v1/auth/anonymous/upgrade/${provider}/callback?${q}`, void 0, void 0, mine.token);
1272
+ if (done2.error) return failedTo(done2.error.code);
1273
+ const s2 = await stored(done2.data);
1274
+ if (s2 === null) return failedTo("unavailable");
1275
+ return redirect(back, [...await write(request, s2, readCookies(request.headers.get("cookie"))), clear]);
1276
+ }
1229
1277
  if (step.kind === "link") {
1230
1278
  const mine = await signedInAs(request);
1231
1279
  if ("response" in mine) return failedTo("unauthenticated");
@@ -1241,6 +1289,19 @@ function createCauthy(given = {}) {
1241
1289
  if (s === null) return failedTo("unavailable");
1242
1290
  return redirect(back, [...await write(request, s, readCookies(request.headers.get("cookie"))), clear]);
1243
1291
  }
1292
+ if (route.startsWith("/me/upgrade/social/") && !post) {
1293
+ const provider = providerIn(route.slice("/me/upgrade/social/".length));
1294
+ if (!PROVIDER_ID.test(provider)) return new Response("Not found", { status: 404 });
1295
+ const returnTo = localPath(url.searchParams.get("return_to"), afterSignIn);
1296
+ const failed2 = (code) => redirect(`${returnTo}${returnTo.includes("?") ? "&" : "?"}auth_error=${encodeURIComponent(code)}`);
1297
+ const mine = await signedInAs(request);
1298
+ if ("response" in mine) return failed2("unauthenticated");
1299
+ const callback2 = `${basePath}/callback/${provider}`;
1300
+ const started = await ask(request, "GET", `/v1/auth/anonymous/upgrade/${provider}?redirect_uri=${encodeURIComponent(`${originOf(request)}${callback2}`)}`, void 0, callback2, mine.token);
1301
+ if (started.error || typeof started.data?.redirect_url !== "string") return failed2(started.error?.code ?? "provider_unavailable");
1302
+ const step = { kind: "upgrade", token: String(started.data.state ?? ""), provider, returnTo };
1303
+ return redirect(started.data.redirect_url, [...mine.headers.getSetCookie(), writeCookie(stepCookie, await seal(step, await key), attrs(request, STEP_SECONDS))]);
1304
+ }
1244
1305
  if (route.startsWith("/me/identities/link/") && !post) {
1245
1306
  const provider = providerIn(route.slice("/me/identities/link/".length));
1246
1307
  if (!PROVIDER_ID.test(provider)) return new Response("Not found", { status: 404 });
@@ -1278,6 +1339,24 @@ function createCauthy(given = {}) {
1278
1339
  const list = Array.isArray(res.data) ? res.data : [];
1279
1340
  return json({ agents: list.map(agentOf) }, 200, mine.headers);
1280
1341
  }
1342
+ if ((route === "/me/organizations" || route === "/me/organizations/members" || route === "/me/organizations/roles") && !post) {
1343
+ const mine = await signedInAs(request);
1344
+ if ("response" in mine) return mine.response;
1345
+ let path = "/v1/auth/me/organizations";
1346
+ if (route !== "/me/organizations") {
1347
+ const id = url.searchParams.get("id") ?? "";
1348
+ if (!UUID.test(id)) return problem(400, "invalid_organization", "Say which organization.", void 0, mine.headers);
1349
+ path += `/${id}/${route.endsWith("/roles") ? "roles" : "members"}`;
1350
+ } else if (url.searchParams.get("system")) {
1351
+ path += `?system=${encodeURIComponent(url.searchParams.get("system"))}`;
1352
+ }
1353
+ const res = await ask(request, "GET", path, void 0, void 0, mine.token);
1354
+ if (res.error) return problem(res.status, res.error.code, res.error.message, void 0, mine.headers);
1355
+ const list = Array.isArray(res.data) ? res.data : [];
1356
+ if (route === "/me/organizations") return json({ organizations: list.map(seatOf) }, 200, mine.headers);
1357
+ if (route === "/me/organizations/roles") return json({ roles: list.map(orgRoleOf) }, 200, mine.headers);
1358
+ return json({ members: list.map(orgMemberOf) }, 200, mine.headers);
1359
+ }
1281
1360
  if (route === "/me/mfa/factors" && !post) {
1282
1361
  const mine = await signedInAs(request);
1283
1362
  if ("response" in mine) return mine.response;
@@ -1296,6 +1375,28 @@ function createCauthy(given = {}) {
1296
1375
  }
1297
1376
  return json({ account: accountOf(res.data) }, 200, mine.headers);
1298
1377
  }
1378
+ if (route === "/sign-in/mfa/push/events" && !post) {
1379
+ const sealed = readCookies(request.headers.get("cookie")).get(stepCookie);
1380
+ const step = sealed ? await unseal(sealed, await key) : null;
1381
+ if (step === null || step.kind !== "mfa") return problem(400, "step_expired", "Sign in again: the code was asked for too long ago.");
1382
+ let upstream;
1383
+ try {
1384
+ upstream = await doFetch(`${issuer}/v1/auth/mfa/push/events`, {
1385
+ headers: { "x-tenant-key": tenant, "x-mfa-token": step.token, accept: "text/event-stream" },
1386
+ signal: request.signal
1387
+ });
1388
+ } catch {
1389
+ return problem(503, "unavailable", "Cauthy could not be reached.");
1390
+ }
1391
+ if (!upstream.ok || !upstream.body) {
1392
+ const b2 = await upstream.json().catch(() => null);
1393
+ return problem(upstream.status, String(b2?.errors?.[0]?.code ?? "error"), String(b2?.errors?.[0]?.message ?? "The request could not be completed."));
1394
+ }
1395
+ return new Response(upstream.body, {
1396
+ status: 200,
1397
+ headers: { "content-type": "text/event-stream", "cache-control": "no-cache, no-store", "x-accel-buffering": "no" }
1398
+ });
1399
+ }
1299
1400
  if (!post) return new Response("Method not allowed", { status: 405, headers: { allow: "POST" } });
1300
1401
  if (!ownRequest(request)) return problem(403, "cross_site", "This request did not come from this application.");
1301
1402
  if (route === "/sign-out") {
@@ -1320,6 +1421,12 @@ function createCauthy(given = {}) {
1320
1421
  const c = res.data?.connection;
1321
1422
  return json(c ? { status: "found", connection: { id: String(c.slug ?? ""), name: String(c.display_name ?? ""), enforced: c.enforced === true } } : { status: "none" });
1322
1423
  }
1424
+ if (route === "/sign-in/anonymous") {
1425
+ if (!post) return new Response("Method not allowed", { status: 405, headers: { allow: "POST" } });
1426
+ const res = await ask(request, "POST", "/v1/auth/anonymous", {});
1427
+ if (res.error) return problem(res.status, res.error.code, res.error.message);
1428
+ return signedIn(request, res.data);
1429
+ }
1323
1430
  if (route === "/sign-in/email") {
1324
1431
  const bad = firstProblem(checkEmail(b.email), checkPassword(b.password));
1325
1432
  if (bad) return invalid(bad);
@@ -1341,6 +1448,19 @@ function createCauthy(given = {}) {
1341
1448
  if (res.error) return problem(res.status, res.error.code, res.error.message, "code");
1342
1449
  return signedIn(request, res.data, [writeCookie(stepCookie, "", attrs(request, 0))]);
1343
1450
  }
1451
+ if (route === "/sign-in/mfa/push" || route === "/sign-in/mfa/push/finish") {
1452
+ const sealed = readCookies(request.headers.get("cookie")).get(stepCookie);
1453
+ const step = sealed ? await unseal(sealed, await key) : null;
1454
+ if (step === null || step.kind !== "mfa") return problem(400, "step_expired", "Sign in again: the code was asked for too long ago.");
1455
+ if (route === "/sign-in/mfa/push") {
1456
+ const res2 = await ask(request, "POST", "/v1/auth/mfa/push", { mfa_token: step.token });
1457
+ if (res2.error) return problem(res2.status, res2.error.code, res2.error.message);
1458
+ return json({ status: "sent", number: Number(res2.data?.number ?? 0) });
1459
+ }
1460
+ const res = await ask(request, "POST", "/v1/auth/mfa/challenge", { mfa_token: step.token, push: true });
1461
+ if (res.error) return problem(res.status, res.error.code, res.error.message);
1462
+ return signedIn(request, res.data, [writeCookie(stepCookie, "", attrs(request, 0))]);
1463
+ }
1344
1464
  if (route === "/sign-in/mfa/methods" || route === "/sign-in/mfa/send") {
1345
1465
  const sealed = readCookies(request.headers.get("cookie")).get(stepCookie);
1346
1466
  const step = sealed ? await unseal(sealed, await key) : null;
@@ -1349,7 +1469,13 @@ function createCauthy(given = {}) {
1349
1469
  const res2 = await ask(request, "POST", "/v1/auth/mfa/methods", { mfa_token: step.token });
1350
1470
  if (res2.error) return problem(res2.status, res2.error.code, res2.error.message);
1351
1471
  const p = res2.data?.phone;
1352
- return json({ status: "ok", totp: res2.data?.totp === true, phone: p ? { number: String(p.number ?? ""), channel: String(p.channel ?? "sms") } : null });
1472
+ const push = res2.data?.push;
1473
+ return json({
1474
+ status: "ok",
1475
+ totp: res2.data?.totp === true,
1476
+ phone: p ? { number: String(p.number ?? ""), channel: String(p.channel ?? "sms") } : null,
1477
+ push: push ? { devices: Number(push.devices ?? 0) } : null
1478
+ });
1353
1479
  }
1354
1480
  const res = await ask(request, "POST", "/v1/auth/mfa/send", { mfa_token: step.token });
1355
1481
  if (res.error) return problem(res.status, res.error.code, res.error.message);
@@ -1483,6 +1609,53 @@ function createCauthy(given = {}) {
1483
1609
  if (res.error) return refused(res);
1484
1610
  return json({ status: "removed", id }, 200, mine.headers);
1485
1611
  }
1612
+ if (route === "/me/upgrade") {
1613
+ const bad = firstProblem(checkName(b.name), checkEmail(b.email), checkNewPassword(b.password));
1614
+ if (bad) return invalid(bad);
1615
+ const res = await as("/v1/auth/anonymous/upgrade", { email: String(b.email).trim(), password: b.password, display_name: typeof b.name === "string" ? b.name.trim() : "" });
1616
+ if (res.error) return refused(res, res.error.code === "weak_password" ? "password" : "email");
1617
+ return signedIn(request, res.data);
1618
+ }
1619
+ if (route.startsWith("/me/organizations/members/")) {
1620
+ const org = typeof b.organizationId === "string" ? b.organizationId : "";
1621
+ if (!UUID.test(org)) return problem(400, "invalid_organization", "Say which organization.", void 0, mine.headers);
1622
+ const base = `/v1/auth/me/organizations/${org}/members`;
1623
+ if (route === "/me/organizations/members/add") {
1624
+ const bad = checkEmail(b.email);
1625
+ if (bad) return invalid(bad);
1626
+ const role = typeof b.role === "string" ? b.role : "";
1627
+ if (role === "") return problem(400, "invalid_role", "Choose a role.", "role", mine.headers);
1628
+ const res = await as(base, {
1629
+ email: String(b.email).trim(),
1630
+ role,
1631
+ name: typeof b.name === "string" ? b.name.trim() : "",
1632
+ client_id: clientId,
1633
+ ...typeof b.locale === "string" && b.locale ? { locale: b.locale } : {}
1634
+ });
1635
+ if (res.error) return refused(res, res.error.code === "unknown_role" ? "role" : "email");
1636
+ return json({ status: "added", member: orgMemberOf(res.data) }, 200, mine.headers);
1637
+ }
1638
+ const user = typeof b.userId === "string" ? b.userId : "";
1639
+ if (!UUID.test(user)) return problem(400, "invalid_member", "Say which member.", void 0, mine.headers);
1640
+ if (route === "/me/organizations/members/role") {
1641
+ const role = typeof b.role === "string" ? b.role : "";
1642
+ if (role === "") return problem(400, "invalid_role", "Choose a role.", "role", mine.headers);
1643
+ const res = await as(`${base}/${user}`, { role }, "PUT");
1644
+ if (res.error) return refused(res, "role");
1645
+ return json({ status: "changed", userId: user, role }, 200, mine.headers);
1646
+ }
1647
+ if (route === "/me/organizations/members/remove") {
1648
+ const res = await as(`${base}/${user}`, void 0, "DELETE");
1649
+ if (res.error) return refused(res);
1650
+ orgCache.delete(mine.token);
1651
+ return json({ status: "removed", userId: user }, 200, mine.headers);
1652
+ }
1653
+ if (route === "/me/organizations/members/invite") {
1654
+ const res = await as(`${base}/${user}/invite`, { client_id: clientId, ...typeof b.locale === "string" && b.locale ? { locale: b.locale } : {} });
1655
+ if (res.error) return refused(res);
1656
+ return json({ status: "sent", userId: user }, 200, mine.headers);
1657
+ }
1658
+ }
1486
1659
  if (route === "/me/agents/disconnect") {
1487
1660
  const id = typeof b.id === "string" ? b.id : "";
1488
1661
  if (!/^[0-9a-f-]{36}$/i.test(id)) return problem(400, "invalid_agent", "Say which agent to disconnect.", void 0, mine.headers);