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.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 ?? ""),
|
|
@@ -1133,8 +1160,17 @@ function createCauthy(given = {}) {
|
|
|
1133
1160
|
"/me/passkeys/add/finish",
|
|
1134
1161
|
"/me/passkeys/remove",
|
|
1135
1162
|
"/me/agents",
|
|
1136
|
-
"/me/agents/disconnect"
|
|
1137
|
-
|
|
1163
|
+
"/me/agents/disconnect",
|
|
1164
|
+
"/sign-in/anonymous",
|
|
1165
|
+
"/me/upgrade",
|
|
1166
|
+
"/me/organizations",
|
|
1167
|
+
"/me/organizations/members",
|
|
1168
|
+
"/me/organizations/roles",
|
|
1169
|
+
"/me/organizations/members/add",
|
|
1170
|
+
"/me/organizations/members/role",
|
|
1171
|
+
"/me/organizations/members/remove",
|
|
1172
|
+
"/me/organizations/members/invite"
|
|
1173
|
+
].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
1174
|
if (!own) return null;
|
|
1139
1175
|
if (tenant === "") {
|
|
1140
1176
|
return problem(500, "not_configured", "cauthy-auth: tenant (CAUTHY_TENANT) is required for the application's own sign-in screens");
|
|
@@ -1147,10 +1183,11 @@ function createCauthy(given = {}) {
|
|
|
1147
1183
|
return json(lookCache.look);
|
|
1148
1184
|
}
|
|
1149
1185
|
if (route === "/methods" && !post) {
|
|
1150
|
-
const [providers, settings, place] = await Promise.all([
|
|
1186
|
+
const [providers, settings, place, sso] = await Promise.all([
|
|
1151
1187
|
ask(request, "GET", "/v1/auth/social/providers"),
|
|
1152
1188
|
ask(request, "GET", "/v1/auth/settings"),
|
|
1153
|
-
ask(request, "GET", `/v1/auth/webauthn/place?origin=${encodeURIComponent(originOf(request))}`)
|
|
1189
|
+
ask(request, "GET", `/v1/auth/webauthn/place?origin=${encodeURIComponent(originOf(request))}`),
|
|
1190
|
+
ask(request, "GET", "/v1/auth/sso/connections")
|
|
1154
1191
|
]);
|
|
1155
1192
|
const list = Array.isArray(providers.data) ? providers.data : [];
|
|
1156
1193
|
const here = place.data?.here === true;
|
|
@@ -1162,9 +1199,46 @@ function createCauthy(given = {}) {
|
|
|
1162
1199
|
passkey: place.error ? true : here || place.data?.on_cauthy === true,
|
|
1163
1200
|
passkeyHere: here,
|
|
1164
1201
|
passkeyOnCauthy: place.error ? true : place.data?.on_cauthy === true,
|
|
1202
|
+
// A company's sign-in, found by the person's work address.
|
|
1203
|
+
sso: Array.isArray(sso.data) && sso.data.some((c) => c?.discoverable === true),
|
|
1165
1204
|
...settings.data?.captcha_enabled === true && settings.data?.captcha_site_key ? { captchaSiteKey: String(settings.data.captcha_site_key) } : {}
|
|
1166
1205
|
});
|
|
1167
1206
|
}
|
|
1207
|
+
if (route === "/sign-in/sso" && !post) {
|
|
1208
|
+
const returnTo = localPath(url.searchParams.get("return_to"), afterSignIn);
|
|
1209
|
+
const failed2 = (code) => redirect(`${returnTo}${returnTo.includes("?") ? "&" : "?"}auth_error=${encodeURIComponent(code)}`);
|
|
1210
|
+
const email = (url.searchParams.get("email") ?? "").trim();
|
|
1211
|
+
const connection = (url.searchParams.get("connection") ?? "").trim();
|
|
1212
|
+
if (email === "" && connection === "") return failed2("sso_not_found");
|
|
1213
|
+
const verifier = random(48);
|
|
1214
|
+
const challenge = b64url(new Uint8Array(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(verifier))));
|
|
1215
|
+
const callback2 = `${basePath}/sso/callback`;
|
|
1216
|
+
const started = await ask(request, "POST", "/v1/auth/sso/start", {
|
|
1217
|
+
...connection ? { connection } : { email },
|
|
1218
|
+
redirect_uri: `${originOf(request)}${callback2}`,
|
|
1219
|
+
code_challenge: challenge
|
|
1220
|
+
}, callback2);
|
|
1221
|
+
if (started.error || typeof started.data?.redirect_url !== "string") return failed2(started.error?.code ?? "sso_unavailable");
|
|
1222
|
+
const step = { kind: "sso", token: verifier, returnTo };
|
|
1223
|
+
return redirect(started.data.redirect_url, [writeCookie(stepCookie, await seal(step, await key), attrs(request, STEP_SECONDS))]);
|
|
1224
|
+
}
|
|
1225
|
+
if (route === "/sso/callback" && !post) {
|
|
1226
|
+
const sealed = readCookies(request.headers.get("cookie")).get(stepCookie);
|
|
1227
|
+
const step = sealed ? await unseal(sealed, await key) : null;
|
|
1228
|
+
const clear = writeCookie(stepCookie, "", attrs(request, 0));
|
|
1229
|
+
const back = step?.returnTo ?? afterSignIn;
|
|
1230
|
+
const failedTo = (code2) => redirect(`${back}${back.includes("?") ? "&" : "?"}auth_error=${encodeURIComponent(code2)}`, [clear]);
|
|
1231
|
+
if (step === null || step.kind !== "sso") return failedTo("state_mismatch");
|
|
1232
|
+
const refused = url.searchParams.get("error");
|
|
1233
|
+
if (refused) return failedTo(refused);
|
|
1234
|
+
const code = url.searchParams.get("code");
|
|
1235
|
+
if (!code) return failedTo("sso_failed");
|
|
1236
|
+
const done = await ask(request, "POST", "/v1/auth/sso/token", { code, redirect_uri: `${originOf(request)}${basePath}/sso/callback`, code_verifier: step.token });
|
|
1237
|
+
if (done.error) return failedTo(done.error.code);
|
|
1238
|
+
const s = await stored(done.data);
|
|
1239
|
+
if (s === null) return failedTo("unavailable");
|
|
1240
|
+
return redirect(back, [...await write(request, s, readCookies(request.headers.get("cookie"))), clear]);
|
|
1241
|
+
}
|
|
1168
1242
|
if (route.startsWith("/sign-in/social/") && !post) {
|
|
1169
1243
|
const provider = providerIn(route.slice("/sign-in/social/".length));
|
|
1170
1244
|
if (!PROVIDER_ID.test(provider)) return new Response("Not found", { status: 404 });
|
|
@@ -1184,10 +1258,19 @@ function createCauthy(given = {}) {
|
|
|
1184
1258
|
const clear = writeCookie(stepCookie, "", attrs(request, 0));
|
|
1185
1259
|
const back = step?.returnTo ?? afterSignIn;
|
|
1186
1260
|
const failedTo = (code2) => redirect(`${back}${back.includes("?") ? "&" : "?"}auth_error=${encodeURIComponent(code2)}`, [clear]);
|
|
1187
|
-
if (step === null || step.kind !== "social" && step.kind !== "link" || step.provider !== provider || url.searchParams.get("state") !== step.token) return failedTo("state_mismatch");
|
|
1261
|
+
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");
|
|
1188
1262
|
const code = url.searchParams.get("code");
|
|
1189
1263
|
if (!code) return failedTo(url.searchParams.get("error") === "access_denied" ? "cancelled" : "provider_refused");
|
|
1190
1264
|
const q = new URLSearchParams({ code, state: step.token, redirect_uri: `${originOf(request)}${basePath}/callback/${provider}` });
|
|
1265
|
+
if (step.kind === "upgrade") {
|
|
1266
|
+
const mine = await signedInAs(request);
|
|
1267
|
+
if ("response" in mine) return failedTo("unauthenticated");
|
|
1268
|
+
const done2 = await ask(request, "GET", `/v1/auth/anonymous/upgrade/${provider}/callback?${q}`, void 0, void 0, mine.token);
|
|
1269
|
+
if (done2.error) return failedTo(done2.error.code);
|
|
1270
|
+
const s2 = await stored(done2.data);
|
|
1271
|
+
if (s2 === null) return failedTo("unavailable");
|
|
1272
|
+
return redirect(back, [...await write(request, s2, readCookies(request.headers.get("cookie"))), clear]);
|
|
1273
|
+
}
|
|
1191
1274
|
if (step.kind === "link") {
|
|
1192
1275
|
const mine = await signedInAs(request);
|
|
1193
1276
|
if ("response" in mine) return failedTo("unauthenticated");
|
|
@@ -1203,6 +1286,19 @@ function createCauthy(given = {}) {
|
|
|
1203
1286
|
if (s === null) return failedTo("unavailable");
|
|
1204
1287
|
return redirect(back, [...await write(request, s, readCookies(request.headers.get("cookie"))), clear]);
|
|
1205
1288
|
}
|
|
1289
|
+
if (route.startsWith("/me/upgrade/social/") && !post) {
|
|
1290
|
+
const provider = providerIn(route.slice("/me/upgrade/social/".length));
|
|
1291
|
+
if (!PROVIDER_ID.test(provider)) return new Response("Not found", { status: 404 });
|
|
1292
|
+
const returnTo = localPath(url.searchParams.get("return_to"), afterSignIn);
|
|
1293
|
+
const failed2 = (code) => redirect(`${returnTo}${returnTo.includes("?") ? "&" : "?"}auth_error=${encodeURIComponent(code)}`);
|
|
1294
|
+
const mine = await signedInAs(request);
|
|
1295
|
+
if ("response" in mine) return failed2("unauthenticated");
|
|
1296
|
+
const callback2 = `${basePath}/callback/${provider}`;
|
|
1297
|
+
const started = await ask(request, "GET", `/v1/auth/anonymous/upgrade/${provider}?redirect_uri=${encodeURIComponent(`${originOf(request)}${callback2}`)}`, void 0, callback2, mine.token);
|
|
1298
|
+
if (started.error || typeof started.data?.redirect_url !== "string") return failed2(started.error?.code ?? "provider_unavailable");
|
|
1299
|
+
const step = { kind: "upgrade", token: String(started.data.state ?? ""), provider, returnTo };
|
|
1300
|
+
return redirect(started.data.redirect_url, [...mine.headers.getSetCookie(), writeCookie(stepCookie, await seal(step, await key), attrs(request, STEP_SECONDS))]);
|
|
1301
|
+
}
|
|
1206
1302
|
if (route.startsWith("/me/identities/link/") && !post) {
|
|
1207
1303
|
const provider = providerIn(route.slice("/me/identities/link/".length));
|
|
1208
1304
|
if (!PROVIDER_ID.test(provider)) return new Response("Not found", { status: 404 });
|
|
@@ -1240,6 +1336,24 @@ function createCauthy(given = {}) {
|
|
|
1240
1336
|
const list = Array.isArray(res.data) ? res.data : [];
|
|
1241
1337
|
return json({ agents: list.map(agentOf) }, 200, mine.headers);
|
|
1242
1338
|
}
|
|
1339
|
+
if ((route === "/me/organizations" || route === "/me/organizations/members" || route === "/me/organizations/roles") && !post) {
|
|
1340
|
+
const mine = await signedInAs(request);
|
|
1341
|
+
if ("response" in mine) return mine.response;
|
|
1342
|
+
let path = "/v1/auth/me/organizations";
|
|
1343
|
+
if (route !== "/me/organizations") {
|
|
1344
|
+
const id = url.searchParams.get("id") ?? "";
|
|
1345
|
+
if (!UUID.test(id)) return problem(400, "invalid_organization", "Say which organization.", void 0, mine.headers);
|
|
1346
|
+
path += `/${id}/${route.endsWith("/roles") ? "roles" : "members"}`;
|
|
1347
|
+
} else if (url.searchParams.get("system")) {
|
|
1348
|
+
path += `?system=${encodeURIComponent(url.searchParams.get("system"))}`;
|
|
1349
|
+
}
|
|
1350
|
+
const res = await ask(request, "GET", path, void 0, void 0, mine.token);
|
|
1351
|
+
if (res.error) return problem(res.status, res.error.code, res.error.message, void 0, mine.headers);
|
|
1352
|
+
const list = Array.isArray(res.data) ? res.data : [];
|
|
1353
|
+
if (route === "/me/organizations") return json({ organizations: list.map(seatOf) }, 200, mine.headers);
|
|
1354
|
+
if (route === "/me/organizations/roles") return json({ roles: list.map(orgRoleOf) }, 200, mine.headers);
|
|
1355
|
+
return json({ members: list.map(orgMemberOf) }, 200, mine.headers);
|
|
1356
|
+
}
|
|
1243
1357
|
if (route === "/me/mfa/factors" && !post) {
|
|
1244
1358
|
const mine = await signedInAs(request);
|
|
1245
1359
|
if ("response" in mine) return mine.response;
|
|
@@ -1274,6 +1388,20 @@ function createCauthy(given = {}) {
|
|
|
1274
1388
|
}
|
|
1275
1389
|
const b = await body(request);
|
|
1276
1390
|
if (b === null) return problem(400, "bad_request", "Send the form as JSON.");
|
|
1391
|
+
if (route === "/sign-in/sso/discover") {
|
|
1392
|
+
const bad = checkEmail(b.email);
|
|
1393
|
+
if (bad) return invalid(bad);
|
|
1394
|
+
const res = await ask(request, "POST", "/v1/auth/sso/discover", { email: String(b.email).trim() });
|
|
1395
|
+
if (res.error) return problem(res.status, res.error.code, res.error.message);
|
|
1396
|
+
const c = res.data?.connection;
|
|
1397
|
+
return json(c ? { status: "found", connection: { id: String(c.slug ?? ""), name: String(c.display_name ?? ""), enforced: c.enforced === true } } : { status: "none" });
|
|
1398
|
+
}
|
|
1399
|
+
if (route === "/sign-in/anonymous") {
|
|
1400
|
+
if (!post) return new Response("Method not allowed", { status: 405, headers: { allow: "POST" } });
|
|
1401
|
+
const res = await ask(request, "POST", "/v1/auth/anonymous", {});
|
|
1402
|
+
if (res.error) return problem(res.status, res.error.code, res.error.message);
|
|
1403
|
+
return signedIn(request, res.data);
|
|
1404
|
+
}
|
|
1277
1405
|
if (route === "/sign-in/email") {
|
|
1278
1406
|
const bad = firstProblem(checkEmail(b.email), checkPassword(b.password));
|
|
1279
1407
|
if (bad) return invalid(bad);
|
|
@@ -1437,6 +1565,53 @@ function createCauthy(given = {}) {
|
|
|
1437
1565
|
if (res.error) return refused(res);
|
|
1438
1566
|
return json({ status: "removed", id }, 200, mine.headers);
|
|
1439
1567
|
}
|
|
1568
|
+
if (route === "/me/upgrade") {
|
|
1569
|
+
const bad = firstProblem(checkName(b.name), checkEmail(b.email), checkNewPassword(b.password));
|
|
1570
|
+
if (bad) return invalid(bad);
|
|
1571
|
+
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() : "" });
|
|
1572
|
+
if (res.error) return refused(res, res.error.code === "weak_password" ? "password" : "email");
|
|
1573
|
+
return signedIn(request, res.data);
|
|
1574
|
+
}
|
|
1575
|
+
if (route.startsWith("/me/organizations/members/")) {
|
|
1576
|
+
const org = typeof b.organizationId === "string" ? b.organizationId : "";
|
|
1577
|
+
if (!UUID.test(org)) return problem(400, "invalid_organization", "Say which organization.", void 0, mine.headers);
|
|
1578
|
+
const base = `/v1/auth/me/organizations/${org}/members`;
|
|
1579
|
+
if (route === "/me/organizations/members/add") {
|
|
1580
|
+
const bad = checkEmail(b.email);
|
|
1581
|
+
if (bad) return invalid(bad);
|
|
1582
|
+
const role = typeof b.role === "string" ? b.role : "";
|
|
1583
|
+
if (role === "") return problem(400, "invalid_role", "Choose a role.", "role", mine.headers);
|
|
1584
|
+
const res = await as(base, {
|
|
1585
|
+
email: String(b.email).trim(),
|
|
1586
|
+
role,
|
|
1587
|
+
name: typeof b.name === "string" ? b.name.trim() : "",
|
|
1588
|
+
client_id: clientId,
|
|
1589
|
+
...typeof b.locale === "string" && b.locale ? { locale: b.locale } : {}
|
|
1590
|
+
});
|
|
1591
|
+
if (res.error) return refused(res, res.error.code === "unknown_role" ? "role" : "email");
|
|
1592
|
+
return json({ status: "added", member: orgMemberOf(res.data) }, 200, mine.headers);
|
|
1593
|
+
}
|
|
1594
|
+
const user = typeof b.userId === "string" ? b.userId : "";
|
|
1595
|
+
if (!UUID.test(user)) return problem(400, "invalid_member", "Say which member.", void 0, mine.headers);
|
|
1596
|
+
if (route === "/me/organizations/members/role") {
|
|
1597
|
+
const role = typeof b.role === "string" ? b.role : "";
|
|
1598
|
+
if (role === "") return problem(400, "invalid_role", "Choose a role.", "role", mine.headers);
|
|
1599
|
+
const res = await as(`${base}/${user}`, { role }, "PUT");
|
|
1600
|
+
if (res.error) return refused(res, "role");
|
|
1601
|
+
return json({ status: "changed", userId: user, role }, 200, mine.headers);
|
|
1602
|
+
}
|
|
1603
|
+
if (route === "/me/organizations/members/remove") {
|
|
1604
|
+
const res = await as(`${base}/${user}`, void 0, "DELETE");
|
|
1605
|
+
if (res.error) return refused(res);
|
|
1606
|
+
orgCache.delete(mine.token);
|
|
1607
|
+
return json({ status: "removed", userId: user }, 200, mine.headers);
|
|
1608
|
+
}
|
|
1609
|
+
if (route === "/me/organizations/members/invite") {
|
|
1610
|
+
const res = await as(`${base}/${user}/invite`, { client_id: clientId, ...typeof b.locale === "string" && b.locale ? { locale: b.locale } : {} });
|
|
1611
|
+
if (res.error) return refused(res);
|
|
1612
|
+
return json({ status: "sent", userId: user }, 200, mine.headers);
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1440
1615
|
if (route === "/me/agents/disconnect") {
|
|
1441
1616
|
const id = typeof b.id === "string" ? b.id : "";
|
|
1442
1617
|
if (!/^[0-9a-f-]{36}$/i.test(id)) return problem(400, "invalid_agent", "Say which agent to disconnect.", void 0, mine.headers);
|