cauthy-auth 0.22.0 → 0.24.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/index.js CHANGED
@@ -700,7 +700,6 @@ async function verifyWebhook(request, options = {}) {
700
700
  try {
701
701
  const verified = await (0, import_jose3.jwtVerify)(signature, options.jwks ?? keysOf(issuer), {
702
702
  algorithms: ["RS256"],
703
- issuer,
704
703
  audience,
705
704
  typ: "cauthy-webhook+jwt",
706
705
  requiredClaims: ["exp", "iat", "jti", "body_sha256"],
@@ -711,6 +710,9 @@ async function verifyWebhook(request, options = {}) {
711
710
  } catch (err) {
712
711
  throw new CauthyWebhookError(err instanceof Error ? err.message : "bad signature");
713
712
  }
713
+ if (claims.iss !== issuer && claims.domain_iss !== issuer) {
714
+ throw new CauthyWebhookError('unexpected "iss" claim value');
715
+ }
714
716
  const now = Math.floor((options.now ?? /* @__PURE__ */ new Date()).getTime() / 1e3);
715
717
  if (typeof claims.iat !== "number" || claims.iat > now + 30) throw new CauthyWebhookError("signed in the future");
716
718
  const digest = new Uint8Array(await crypto.subtle.digest("SHA-256", raw));
@@ -1191,6 +1193,9 @@ function createCauthy(given = {}) {
1191
1193
  "/me/mfa/phone/remove",
1192
1194
  "/sign-in/mfa/methods",
1193
1195
  "/sign-in/mfa/send",
1196
+ "/sign-in/mfa/push",
1197
+ "/sign-in/mfa/push/events",
1198
+ "/sign-in/mfa/push/finish",
1194
1199
  "/me/sessions",
1195
1200
  "/me/sessions/end",
1196
1201
  "/me/email",
@@ -1420,6 +1425,28 @@ function createCauthy(given = {}) {
1420
1425
  }
1421
1426
  return json({ account: accountOf(res.data) }, 200, mine.headers);
1422
1427
  }
1428
+ if (route === "/sign-in/mfa/push/events" && !post) {
1429
+ const sealed = readCookies(request.headers.get("cookie")).get(stepCookie);
1430
+ const step = sealed ? await unseal(sealed, await key) : null;
1431
+ if (step === null || step.kind !== "mfa") return problem(400, "step_expired", "Sign in again: the code was asked for too long ago.");
1432
+ let upstream;
1433
+ try {
1434
+ upstream = await doFetch(`${issuer}/v1/auth/mfa/push/events`, {
1435
+ headers: { "x-tenant-key": tenant, "x-mfa-token": step.token, accept: "text/event-stream" },
1436
+ signal: request.signal
1437
+ });
1438
+ } catch {
1439
+ return problem(503, "unavailable", "Cauthy could not be reached.");
1440
+ }
1441
+ if (!upstream.ok || !upstream.body) {
1442
+ const b2 = await upstream.json().catch(() => null);
1443
+ return problem(upstream.status, String(b2?.errors?.[0]?.code ?? "error"), String(b2?.errors?.[0]?.message ?? "The request could not be completed."));
1444
+ }
1445
+ return new Response(upstream.body, {
1446
+ status: 200,
1447
+ headers: { "content-type": "text/event-stream", "cache-control": "no-cache, no-store", "x-accel-buffering": "no" }
1448
+ });
1449
+ }
1423
1450
  if (!post) return new Response("Method not allowed", { status: 405, headers: { allow: "POST" } });
1424
1451
  if (!ownRequest(request)) return problem(403, "cross_site", "This request did not come from this application.");
1425
1452
  if (route === "/sign-out") {
@@ -1471,6 +1498,19 @@ function createCauthy(given = {}) {
1471
1498
  if (res.error) return problem(res.status, res.error.code, res.error.message, "code");
1472
1499
  return signedIn(request, res.data, [writeCookie(stepCookie, "", attrs(request, 0))]);
1473
1500
  }
1501
+ if (route === "/sign-in/mfa/push" || route === "/sign-in/mfa/push/finish") {
1502
+ const sealed = readCookies(request.headers.get("cookie")).get(stepCookie);
1503
+ const step = sealed ? await unseal(sealed, await key) : null;
1504
+ if (step === null || step.kind !== "mfa") return problem(400, "step_expired", "Sign in again: the code was asked for too long ago.");
1505
+ if (route === "/sign-in/mfa/push") {
1506
+ const res2 = await ask(request, "POST", "/v1/auth/mfa/push", { mfa_token: step.token });
1507
+ if (res2.error) return problem(res2.status, res2.error.code, res2.error.message);
1508
+ return json({ status: "sent", number: Number(res2.data?.number ?? 0) });
1509
+ }
1510
+ const res = await ask(request, "POST", "/v1/auth/mfa/challenge", { mfa_token: step.token, push: true });
1511
+ if (res.error) return problem(res.status, res.error.code, res.error.message);
1512
+ return signedIn(request, res.data, [writeCookie(stepCookie, "", attrs(request, 0))]);
1513
+ }
1474
1514
  if (route === "/sign-in/mfa/methods" || route === "/sign-in/mfa/send") {
1475
1515
  const sealed = readCookies(request.headers.get("cookie")).get(stepCookie);
1476
1516
  const step = sealed ? await unseal(sealed, await key) : null;
@@ -1479,7 +1519,13 @@ function createCauthy(given = {}) {
1479
1519
  const res2 = await ask(request, "POST", "/v1/auth/mfa/methods", { mfa_token: step.token });
1480
1520
  if (res2.error) return problem(res2.status, res2.error.code, res2.error.message);
1481
1521
  const p = res2.data?.phone;
1482
- return json({ status: "ok", totp: res2.data?.totp === true, phone: p ? { number: String(p.number ?? ""), channel: String(p.channel ?? "sms") } : null });
1522
+ const push = res2.data?.push;
1523
+ return json({
1524
+ status: "ok",
1525
+ totp: res2.data?.totp === true,
1526
+ phone: p ? { number: String(p.number ?? ""), channel: String(p.channel ?? "sms") } : null,
1527
+ push: push ? { devices: Number(push.devices ?? 0) } : null
1528
+ });
1483
1529
  }
1484
1530
  const res = await ask(request, "POST", "/v1/auth/mfa/send", { mfa_token: step.token });
1485
1531
  if (res.error) return problem(res.status, res.error.code, res.error.message);