cauthy-auth 0.19.0 → 0.22.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/{cauthy-Bn3iv50y.d.ts → cauthy-DGAy45G2.d.ts} +1 -1
- package/dist/{cauthy-C29HCvag.d.mts → cauthy-XkIbG5gE.d.mts} +1 -1
- package/dist/client.d.mts +157 -2
- package/dist/client.d.ts +157 -2
- package/dist/client.js +37 -2
- package/dist/client.js.map +1 -1
- package/dist/client.mjs +37 -2
- package/dist/client.mjs.map +1 -1
- package/dist/express.d.mts +2 -2
- package/dist/express.d.ts +2 -2
- package/dist/fastify.d.mts +2 -2
- package/dist/fastify.d.ts +2 -2
- package/dist/hono.d.mts +2 -2
- package/dist/hono.d.ts +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +181 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +181 -6
- package/dist/index.mjs.map +1 -1
- package/dist/next.d.mts +2 -2
- package/dist/next.d.ts +2 -2
- package/dist/react.d.mts +192 -1
- package/dist/react.d.ts +192 -1
- package/dist/react.js +279 -23
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +278 -23
- package/dist/react.mjs.map +1 -1
- package/dist/svelte.d.mts +3 -3
- package/dist/svelte.d.ts +3 -3
- package/dist/svelte.js +37 -2
- package/dist/svelte.js.map +1 -1
- package/dist/svelte.mjs +37 -2
- package/dist/svelte.mjs.map +1 -1
- package/dist/{system-ZD_Wa8Bm.d.mts → system-BxMsSIu1.d.mts} +2 -0
- package/dist/{system-DhRr_WxR.d.ts → system-DTIeDXDP.d.ts} +2 -0
- package/dist/vue.d.mts +3 -3
- package/dist/vue.d.ts +3 -3
- package/dist/vue.js +37 -2
- package/dist/vue.js.map +1 -1
- package/dist/vue.mjs +37 -2
- package/dist/vue.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -837,7 +837,8 @@ function createCauthy(given = {}) {
|
|
|
837
837
|
emailVerified: b.email_verified === true,
|
|
838
838
|
restricted: b.restricted === true,
|
|
839
839
|
...typeof b.email_verify_by === "string" ? { emailVerifyBy: b.email_verify_by } : {},
|
|
840
|
-
...typeof b.locale === "string" && b.locale !== "" ? { locale: b.locale } : {}
|
|
840
|
+
...typeof b.locale === "string" && b.locale !== "" ? { locale: b.locale } : {},
|
|
841
|
+
...b.anonymous === true ? { isAnonymous: true } : {}
|
|
841
842
|
}
|
|
842
843
|
};
|
|
843
844
|
} catch {
|
|
@@ -1046,6 +1047,32 @@ function createCauthy(given = {}) {
|
|
|
1046
1047
|
createdAt: String(d?.created_at ?? ""),
|
|
1047
1048
|
lastUsedAt: d?.last_used_at ? String(d.last_used_at) : null
|
|
1048
1049
|
});
|
|
1050
|
+
const UUID = /^[0-9a-f-]{36}$/i;
|
|
1051
|
+
const seatOf = (d) => ({
|
|
1052
|
+
id: String(d?.id ?? ""),
|
|
1053
|
+
system: String(d?.system ?? ""),
|
|
1054
|
+
name: String(d?.name ?? ""),
|
|
1055
|
+
kind: String(d?.kind ?? ""),
|
|
1056
|
+
role: String(d?.role ?? ""),
|
|
1057
|
+
can: { readMembers: d?.can?.read_members === true, manageMembers: d?.can?.manage_members === true }
|
|
1058
|
+
});
|
|
1059
|
+
const orgMemberOf = (d) => ({
|
|
1060
|
+
userId: String(d?.user_id ?? ""),
|
|
1061
|
+
email: String(d?.email ?? ""),
|
|
1062
|
+
name: String(d?.name ?? ""),
|
|
1063
|
+
role: String(d?.role ?? ""),
|
|
1064
|
+
status: String(d?.status ?? ""),
|
|
1065
|
+
invited: d?.invited === true,
|
|
1066
|
+
manager: d?.manager === true,
|
|
1067
|
+
you: d?.you === true,
|
|
1068
|
+
since: String(d?.since ?? "")
|
|
1069
|
+
});
|
|
1070
|
+
const orgRoleOf = (d) => ({
|
|
1071
|
+
role: String(d?.role ?? ""),
|
|
1072
|
+
name: String(d?.name ?? ""),
|
|
1073
|
+
description: String(d?.description ?? ""),
|
|
1074
|
+
manager: d?.manager === true
|
|
1075
|
+
});
|
|
1049
1076
|
const agentOf = (d) => ({
|
|
1050
1077
|
id: String(d?.id ?? ""),
|
|
1051
1078
|
name: String(d?.agent?.name ?? ""),
|
|
@@ -1181,8 +1208,17 @@ function createCauthy(given = {}) {
|
|
|
1181
1208
|
"/me/passkeys/add/finish",
|
|
1182
1209
|
"/me/passkeys/remove",
|
|
1183
1210
|
"/me/agents",
|
|
1184
|
-
"/me/agents/disconnect"
|
|
1185
|
-
|
|
1211
|
+
"/me/agents/disconnect",
|
|
1212
|
+
"/sign-in/anonymous",
|
|
1213
|
+
"/me/upgrade",
|
|
1214
|
+
"/me/organizations",
|
|
1215
|
+
"/me/organizations/members",
|
|
1216
|
+
"/me/organizations/roles",
|
|
1217
|
+
"/me/organizations/members/add",
|
|
1218
|
+
"/me/organizations/members/role",
|
|
1219
|
+
"/me/organizations/members/remove",
|
|
1220
|
+
"/me/organizations/members/invite"
|
|
1221
|
+
].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";
|
|
1186
1222
|
if (!own) return null;
|
|
1187
1223
|
if (tenant === "") {
|
|
1188
1224
|
return problem(500, "not_configured", "cauthy-auth: tenant (CAUTHY_TENANT) is required for the application's own sign-in screens");
|
|
@@ -1195,10 +1231,11 @@ function createCauthy(given = {}) {
|
|
|
1195
1231
|
return json(lookCache.look);
|
|
1196
1232
|
}
|
|
1197
1233
|
if (route === "/methods" && !post) {
|
|
1198
|
-
const [providers, settings, place] = await Promise.all([
|
|
1234
|
+
const [providers, settings, place, sso] = await Promise.all([
|
|
1199
1235
|
ask(request, "GET", "/v1/auth/social/providers"),
|
|
1200
1236
|
ask(request, "GET", "/v1/auth/settings"),
|
|
1201
|
-
ask(request, "GET", `/v1/auth/webauthn/place?origin=${encodeURIComponent(originOf(request))}`)
|
|
1237
|
+
ask(request, "GET", `/v1/auth/webauthn/place?origin=${encodeURIComponent(originOf(request))}`),
|
|
1238
|
+
ask(request, "GET", "/v1/auth/sso/connections")
|
|
1202
1239
|
]);
|
|
1203
1240
|
const list = Array.isArray(providers.data) ? providers.data : [];
|
|
1204
1241
|
const here = place.data?.here === true;
|
|
@@ -1210,9 +1247,46 @@ function createCauthy(given = {}) {
|
|
|
1210
1247
|
passkey: place.error ? true : here || place.data?.on_cauthy === true,
|
|
1211
1248
|
passkeyHere: here,
|
|
1212
1249
|
passkeyOnCauthy: place.error ? true : place.data?.on_cauthy === true,
|
|
1250
|
+
// A company's sign-in, found by the person's work address.
|
|
1251
|
+
sso: Array.isArray(sso.data) && sso.data.some((c) => c?.discoverable === true),
|
|
1213
1252
|
...settings.data?.captcha_enabled === true && settings.data?.captcha_site_key ? { captchaSiteKey: String(settings.data.captcha_site_key) } : {}
|
|
1214
1253
|
});
|
|
1215
1254
|
}
|
|
1255
|
+
if (route === "/sign-in/sso" && !post) {
|
|
1256
|
+
const returnTo = localPath(url.searchParams.get("return_to"), afterSignIn);
|
|
1257
|
+
const failed2 = (code) => redirect(`${returnTo}${returnTo.includes("?") ? "&" : "?"}auth_error=${encodeURIComponent(code)}`);
|
|
1258
|
+
const email = (url.searchParams.get("email") ?? "").trim();
|
|
1259
|
+
const connection = (url.searchParams.get("connection") ?? "").trim();
|
|
1260
|
+
if (email === "" && connection === "") return failed2("sso_not_found");
|
|
1261
|
+
const verifier = random(48);
|
|
1262
|
+
const challenge = b64url(new Uint8Array(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(verifier))));
|
|
1263
|
+
const callback2 = `${basePath}/sso/callback`;
|
|
1264
|
+
const started = await ask(request, "POST", "/v1/auth/sso/start", {
|
|
1265
|
+
...connection ? { connection } : { email },
|
|
1266
|
+
redirect_uri: `${originOf(request)}${callback2}`,
|
|
1267
|
+
code_challenge: challenge
|
|
1268
|
+
}, callback2);
|
|
1269
|
+
if (started.error || typeof started.data?.redirect_url !== "string") return failed2(started.error?.code ?? "sso_unavailable");
|
|
1270
|
+
const step = { kind: "sso", token: verifier, returnTo };
|
|
1271
|
+
return redirect(started.data.redirect_url, [writeCookie(stepCookie, await seal(step, await key), attrs(request, STEP_SECONDS))]);
|
|
1272
|
+
}
|
|
1273
|
+
if (route === "/sso/callback" && !post) {
|
|
1274
|
+
const sealed = readCookies(request.headers.get("cookie")).get(stepCookie);
|
|
1275
|
+
const step = sealed ? await unseal(sealed, await key) : null;
|
|
1276
|
+
const clear = writeCookie(stepCookie, "", attrs(request, 0));
|
|
1277
|
+
const back = step?.returnTo ?? afterSignIn;
|
|
1278
|
+
const failedTo = (code2) => redirect(`${back}${back.includes("?") ? "&" : "?"}auth_error=${encodeURIComponent(code2)}`, [clear]);
|
|
1279
|
+
if (step === null || step.kind !== "sso") return failedTo("state_mismatch");
|
|
1280
|
+
const refused = url.searchParams.get("error");
|
|
1281
|
+
if (refused) return failedTo(refused);
|
|
1282
|
+
const code = url.searchParams.get("code");
|
|
1283
|
+
if (!code) return failedTo("sso_failed");
|
|
1284
|
+
const done = await ask(request, "POST", "/v1/auth/sso/token", { code, redirect_uri: `${originOf(request)}${basePath}/sso/callback`, code_verifier: step.token });
|
|
1285
|
+
if (done.error) return failedTo(done.error.code);
|
|
1286
|
+
const s = await stored(done.data);
|
|
1287
|
+
if (s === null) return failedTo("unavailable");
|
|
1288
|
+
return redirect(back, [...await write(request, s, readCookies(request.headers.get("cookie"))), clear]);
|
|
1289
|
+
}
|
|
1216
1290
|
if (route.startsWith("/sign-in/social/") && !post) {
|
|
1217
1291
|
const provider = providerIn(route.slice("/sign-in/social/".length));
|
|
1218
1292
|
if (!PROVIDER_ID.test(provider)) return new Response("Not found", { status: 404 });
|
|
@@ -1232,10 +1306,19 @@ function createCauthy(given = {}) {
|
|
|
1232
1306
|
const clear = writeCookie(stepCookie, "", attrs(request, 0));
|
|
1233
1307
|
const back = step?.returnTo ?? afterSignIn;
|
|
1234
1308
|
const failedTo = (code2) => redirect(`${back}${back.includes("?") ? "&" : "?"}auth_error=${encodeURIComponent(code2)}`, [clear]);
|
|
1235
|
-
if (step === null || step.kind !== "social" && step.kind !== "link" || step.provider !== provider || url.searchParams.get("state") !== step.token) return failedTo("state_mismatch");
|
|
1309
|
+
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");
|
|
1236
1310
|
const code = url.searchParams.get("code");
|
|
1237
1311
|
if (!code) return failedTo(url.searchParams.get("error") === "access_denied" ? "cancelled" : "provider_refused");
|
|
1238
1312
|
const q = new URLSearchParams({ code, state: step.token, redirect_uri: `${originOf(request)}${basePath}/callback/${provider}` });
|
|
1313
|
+
if (step.kind === "upgrade") {
|
|
1314
|
+
const mine = await signedInAs(request);
|
|
1315
|
+
if ("response" in mine) return failedTo("unauthenticated");
|
|
1316
|
+
const done2 = await ask(request, "GET", `/v1/auth/anonymous/upgrade/${provider}/callback?${q}`, void 0, void 0, mine.token);
|
|
1317
|
+
if (done2.error) return failedTo(done2.error.code);
|
|
1318
|
+
const s2 = await stored(done2.data);
|
|
1319
|
+
if (s2 === null) return failedTo("unavailable");
|
|
1320
|
+
return redirect(back, [...await write(request, s2, readCookies(request.headers.get("cookie"))), clear]);
|
|
1321
|
+
}
|
|
1239
1322
|
if (step.kind === "link") {
|
|
1240
1323
|
const mine = await signedInAs(request);
|
|
1241
1324
|
if ("response" in mine) return failedTo("unauthenticated");
|
|
@@ -1251,6 +1334,19 @@ function createCauthy(given = {}) {
|
|
|
1251
1334
|
if (s === null) return failedTo("unavailable");
|
|
1252
1335
|
return redirect(back, [...await write(request, s, readCookies(request.headers.get("cookie"))), clear]);
|
|
1253
1336
|
}
|
|
1337
|
+
if (route.startsWith("/me/upgrade/social/") && !post) {
|
|
1338
|
+
const provider = providerIn(route.slice("/me/upgrade/social/".length));
|
|
1339
|
+
if (!PROVIDER_ID.test(provider)) return new Response("Not found", { status: 404 });
|
|
1340
|
+
const returnTo = localPath(url.searchParams.get("return_to"), afterSignIn);
|
|
1341
|
+
const failed2 = (code) => redirect(`${returnTo}${returnTo.includes("?") ? "&" : "?"}auth_error=${encodeURIComponent(code)}`);
|
|
1342
|
+
const mine = await signedInAs(request);
|
|
1343
|
+
if ("response" in mine) return failed2("unauthenticated");
|
|
1344
|
+
const callback2 = `${basePath}/callback/${provider}`;
|
|
1345
|
+
const started = await ask(request, "GET", `/v1/auth/anonymous/upgrade/${provider}?redirect_uri=${encodeURIComponent(`${originOf(request)}${callback2}`)}`, void 0, callback2, mine.token);
|
|
1346
|
+
if (started.error || typeof started.data?.redirect_url !== "string") return failed2(started.error?.code ?? "provider_unavailable");
|
|
1347
|
+
const step = { kind: "upgrade", token: String(started.data.state ?? ""), provider, returnTo };
|
|
1348
|
+
return redirect(started.data.redirect_url, [...mine.headers.getSetCookie(), writeCookie(stepCookie, await seal(step, await key), attrs(request, STEP_SECONDS))]);
|
|
1349
|
+
}
|
|
1254
1350
|
if (route.startsWith("/me/identities/link/") && !post) {
|
|
1255
1351
|
const provider = providerIn(route.slice("/me/identities/link/".length));
|
|
1256
1352
|
if (!PROVIDER_ID.test(provider)) return new Response("Not found", { status: 404 });
|
|
@@ -1288,6 +1384,24 @@ function createCauthy(given = {}) {
|
|
|
1288
1384
|
const list = Array.isArray(res.data) ? res.data : [];
|
|
1289
1385
|
return json({ agents: list.map(agentOf) }, 200, mine.headers);
|
|
1290
1386
|
}
|
|
1387
|
+
if ((route === "/me/organizations" || route === "/me/organizations/members" || route === "/me/organizations/roles") && !post) {
|
|
1388
|
+
const mine = await signedInAs(request);
|
|
1389
|
+
if ("response" in mine) return mine.response;
|
|
1390
|
+
let path = "/v1/auth/me/organizations";
|
|
1391
|
+
if (route !== "/me/organizations") {
|
|
1392
|
+
const id = url.searchParams.get("id") ?? "";
|
|
1393
|
+
if (!UUID.test(id)) return problem(400, "invalid_organization", "Say which organization.", void 0, mine.headers);
|
|
1394
|
+
path += `/${id}/${route.endsWith("/roles") ? "roles" : "members"}`;
|
|
1395
|
+
} else if (url.searchParams.get("system")) {
|
|
1396
|
+
path += `?system=${encodeURIComponent(url.searchParams.get("system"))}`;
|
|
1397
|
+
}
|
|
1398
|
+
const res = await ask(request, "GET", path, void 0, void 0, mine.token);
|
|
1399
|
+
if (res.error) return problem(res.status, res.error.code, res.error.message, void 0, mine.headers);
|
|
1400
|
+
const list = Array.isArray(res.data) ? res.data : [];
|
|
1401
|
+
if (route === "/me/organizations") return json({ organizations: list.map(seatOf) }, 200, mine.headers);
|
|
1402
|
+
if (route === "/me/organizations/roles") return json({ roles: list.map(orgRoleOf) }, 200, mine.headers);
|
|
1403
|
+
return json({ members: list.map(orgMemberOf) }, 200, mine.headers);
|
|
1404
|
+
}
|
|
1291
1405
|
if (route === "/me/mfa/factors" && !post) {
|
|
1292
1406
|
const mine = await signedInAs(request);
|
|
1293
1407
|
if ("response" in mine) return mine.response;
|
|
@@ -1322,6 +1436,20 @@ function createCauthy(given = {}) {
|
|
|
1322
1436
|
}
|
|
1323
1437
|
const b = await body(request);
|
|
1324
1438
|
if (b === null) return problem(400, "bad_request", "Send the form as JSON.");
|
|
1439
|
+
if (route === "/sign-in/sso/discover") {
|
|
1440
|
+
const bad = checkEmail(b.email);
|
|
1441
|
+
if (bad) return invalid(bad);
|
|
1442
|
+
const res = await ask(request, "POST", "/v1/auth/sso/discover", { email: String(b.email).trim() });
|
|
1443
|
+
if (res.error) return problem(res.status, res.error.code, res.error.message);
|
|
1444
|
+
const c = res.data?.connection;
|
|
1445
|
+
return json(c ? { status: "found", connection: { id: String(c.slug ?? ""), name: String(c.display_name ?? ""), enforced: c.enforced === true } } : { status: "none" });
|
|
1446
|
+
}
|
|
1447
|
+
if (route === "/sign-in/anonymous") {
|
|
1448
|
+
if (!post) return new Response("Method not allowed", { status: 405, headers: { allow: "POST" } });
|
|
1449
|
+
const res = await ask(request, "POST", "/v1/auth/anonymous", {});
|
|
1450
|
+
if (res.error) return problem(res.status, res.error.code, res.error.message);
|
|
1451
|
+
return signedIn(request, res.data);
|
|
1452
|
+
}
|
|
1325
1453
|
if (route === "/sign-in/email") {
|
|
1326
1454
|
const bad = firstProblem(checkEmail(b.email), checkPassword(b.password));
|
|
1327
1455
|
if (bad) return invalid(bad);
|
|
@@ -1485,6 +1613,53 @@ function createCauthy(given = {}) {
|
|
|
1485
1613
|
if (res.error) return refused(res);
|
|
1486
1614
|
return json({ status: "removed", id }, 200, mine.headers);
|
|
1487
1615
|
}
|
|
1616
|
+
if (route === "/me/upgrade") {
|
|
1617
|
+
const bad = firstProblem(checkName(b.name), checkEmail(b.email), checkNewPassword(b.password));
|
|
1618
|
+
if (bad) return invalid(bad);
|
|
1619
|
+
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() : "" });
|
|
1620
|
+
if (res.error) return refused(res, res.error.code === "weak_password" ? "password" : "email");
|
|
1621
|
+
return signedIn(request, res.data);
|
|
1622
|
+
}
|
|
1623
|
+
if (route.startsWith("/me/organizations/members/")) {
|
|
1624
|
+
const org = typeof b.organizationId === "string" ? b.organizationId : "";
|
|
1625
|
+
if (!UUID.test(org)) return problem(400, "invalid_organization", "Say which organization.", void 0, mine.headers);
|
|
1626
|
+
const base = `/v1/auth/me/organizations/${org}/members`;
|
|
1627
|
+
if (route === "/me/organizations/members/add") {
|
|
1628
|
+
const bad = checkEmail(b.email);
|
|
1629
|
+
if (bad) return invalid(bad);
|
|
1630
|
+
const role = typeof b.role === "string" ? b.role : "";
|
|
1631
|
+
if (role === "") return problem(400, "invalid_role", "Choose a role.", "role", mine.headers);
|
|
1632
|
+
const res = await as(base, {
|
|
1633
|
+
email: String(b.email).trim(),
|
|
1634
|
+
role,
|
|
1635
|
+
name: typeof b.name === "string" ? b.name.trim() : "",
|
|
1636
|
+
client_id: clientId,
|
|
1637
|
+
...typeof b.locale === "string" && b.locale ? { locale: b.locale } : {}
|
|
1638
|
+
});
|
|
1639
|
+
if (res.error) return refused(res, res.error.code === "unknown_role" ? "role" : "email");
|
|
1640
|
+
return json({ status: "added", member: orgMemberOf(res.data) }, 200, mine.headers);
|
|
1641
|
+
}
|
|
1642
|
+
const user = typeof b.userId === "string" ? b.userId : "";
|
|
1643
|
+
if (!UUID.test(user)) return problem(400, "invalid_member", "Say which member.", void 0, mine.headers);
|
|
1644
|
+
if (route === "/me/organizations/members/role") {
|
|
1645
|
+
const role = typeof b.role === "string" ? b.role : "";
|
|
1646
|
+
if (role === "") return problem(400, "invalid_role", "Choose a role.", "role", mine.headers);
|
|
1647
|
+
const res = await as(`${base}/${user}`, { role }, "PUT");
|
|
1648
|
+
if (res.error) return refused(res, "role");
|
|
1649
|
+
return json({ status: "changed", userId: user, role }, 200, mine.headers);
|
|
1650
|
+
}
|
|
1651
|
+
if (route === "/me/organizations/members/remove") {
|
|
1652
|
+
const res = await as(`${base}/${user}`, void 0, "DELETE");
|
|
1653
|
+
if (res.error) return refused(res);
|
|
1654
|
+
orgCache.delete(mine.token);
|
|
1655
|
+
return json({ status: "removed", userId: user }, 200, mine.headers);
|
|
1656
|
+
}
|
|
1657
|
+
if (route === "/me/organizations/members/invite") {
|
|
1658
|
+
const res = await as(`${base}/${user}/invite`, { client_id: clientId, ...typeof b.locale === "string" && b.locale ? { locale: b.locale } : {} });
|
|
1659
|
+
if (res.error) return refused(res);
|
|
1660
|
+
return json({ status: "sent", userId: user }, 200, mine.headers);
|
|
1661
|
+
}
|
|
1662
|
+
}
|
|
1488
1663
|
if (route === "/me/agents/disconnect") {
|
|
1489
1664
|
const id = typeof b.id === "string" ? b.id : "";
|
|
1490
1665
|
if (!/^[0-9a-f-]{36}$/i.test(id)) return problem(400, "invalid_agent", "Say which agent to disconnect.", void 0, mine.headers);
|