cauthy-auth 0.22.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.
package/dist/client.d.mts CHANGED
@@ -439,13 +439,34 @@ interface AuthClient {
439
439
  }): Promise<AuthResult<'signed_in', {
440
440
  session: PublicSession;
441
441
  }>>;
442
- /** While the second step is asked for: whether the account has an authenticator app, and the phone (masked) a code can be sent to. */
442
+ /** While the second step is asked for: whether the account has an authenticator app, the phone (masked) a code can be sent to, and phones that approve sign-ins. */
443
443
  mfaMethods(): Promise<AuthResult<'ok', {
444
444
  totp: boolean;
445
445
  phone: {
446
446
  number: string;
447
447
  channel: string;
448
448
  } | null;
449
+ push: {
450
+ devices: number;
451
+ } | null;
452
+ }>>;
453
+ /**
454
+ * Sends a push to the account's phones (the application's app, with
455
+ * cauthy-expo): show `number`, which the person picks on the phone, then
456
+ * call `mfaPushWait`.
457
+ */
458
+ mfaPush(): Promise<AuthResult<'sent', {
459
+ number: number;
460
+ }>>;
461
+ /**
462
+ * Waits for the phone's answer, listening (server-sent events) rather than
463
+ * asking again and again, and signs in when it approves. `denied`: turned
464
+ * down on the phone; `expired`: nobody answered in time.
465
+ */
466
+ mfaPushWait(o?: {
467
+ signal?: AbortSignal;
468
+ }): Promise<AuthResult<'signed_in', {
469
+ session: PublicSession;
449
470
  }>>;
450
471
  /** Sends a code to the account's phone, by SMS or WhatsApp; `mfa` takes it. A few per sign-in. */
451
472
  mfaSendCode(): Promise<AuthResult<'sent', {
package/dist/client.d.ts CHANGED
@@ -439,13 +439,34 @@ interface AuthClient {
439
439
  }): Promise<AuthResult<'signed_in', {
440
440
  session: PublicSession;
441
441
  }>>;
442
- /** While the second step is asked for: whether the account has an authenticator app, and the phone (masked) a code can be sent to. */
442
+ /** While the second step is asked for: whether the account has an authenticator app, the phone (masked) a code can be sent to, and phones that approve sign-ins. */
443
443
  mfaMethods(): Promise<AuthResult<'ok', {
444
444
  totp: boolean;
445
445
  phone: {
446
446
  number: string;
447
447
  channel: string;
448
448
  } | null;
449
+ push: {
450
+ devices: number;
451
+ } | null;
452
+ }>>;
453
+ /**
454
+ * Sends a push to the account's phones (the application's app, with
455
+ * cauthy-expo): show `number`, which the person picks on the phone, then
456
+ * call `mfaPushWait`.
457
+ */
458
+ mfaPush(): Promise<AuthResult<'sent', {
459
+ number: number;
460
+ }>>;
461
+ /**
462
+ * Waits for the phone's answer, listening (server-sent events) rather than
463
+ * asking again and again, and signs in when it approves. `denied`: turned
464
+ * down on the phone; `expired`: nobody answered in time.
465
+ */
466
+ mfaPushWait(o?: {
467
+ signal?: AbortSignal;
468
+ }): Promise<AuthResult<'signed_in', {
469
+ session: PublicSession;
449
470
  }>>;
450
471
  /** Sends a code to the account's phone, by SMS or WhatsApp; `mfa` takes it. A few per sign-in. */
451
472
  mfaSendCode(): Promise<AuthResult<'sent', {
package/dist/client.js CHANGED
@@ -386,6 +386,35 @@ function createAuthClient(options = {}) {
386
386
  mfa: (f) => post("/sign-in/mfa", { code: f.code }, checkCode(f.code)),
387
387
  mfaMethods: () => post("/sign-in/mfa/methods", {}, null),
388
388
  mfaSendCode: () => post("/sign-in/mfa/send", {}, null),
389
+ mfaPush: () => post("/sign-in/mfa/push", {}, null),
390
+ async mfaPushWait(o = {}) {
391
+ const status = await new Promise((resolve) => {
392
+ if (typeof EventSource !== "function") return resolve("approved");
393
+ const source = new EventSource(`${base}/sign-in/mfa/push/events`, { withCredentials: true });
394
+ const stop = (st) => {
395
+ source.close();
396
+ resolve(st);
397
+ };
398
+ o.signal?.addEventListener("abort", () => stop("aborted"));
399
+ source.addEventListener("status", (e) => {
400
+ const st = (() => {
401
+ try {
402
+ return String(JSON.parse(e.data).status);
403
+ } catch {
404
+ return "";
405
+ }
406
+ })();
407
+ if (st && st !== "pending") stop(st);
408
+ });
409
+ source.onerror = () => {
410
+ if (source.readyState === EventSource.CLOSED) stop("expired");
411
+ };
412
+ });
413
+ if (status === "aborted") return { ok: false, error: { code: "aborted", message: "Stopped waiting." } };
414
+ if (status === "denied") return { ok: false, error: { code: "push_denied", message: "The sign-in was turned down on the phone." } };
415
+ if (status === "expired") return { ok: false, error: { code: "push_expired", message: "Nobody answered on the phone in time." } };
416
+ return post("/sign-in/mfa/push/finish", {}, null);
417
+ },
389
418
  magicLink: (f) => post("/sign-in/magic-link", { email: f.email, ...f.create ? { create: true } : {}, ...f.returnTo ? { returnTo: f.returnTo } : {} }, checkEmail(f.email), f.captchaToken),
390
419
  magicLinkVerify: (f) => post("/sign-in/magic-link/verify", { token: f.token }, null),
391
420
  emailCode: (f) => post("/sign-in/email-code", { code: f.code }, checkCode(f.code)),