cauthy-auth 0.18.0 → 0.20.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 +59 -1
- package/dist/client.d.ts +59 -1
- package/dist/client.js +13 -3
- package/dist/client.js.map +1 -1
- package/dist/client.mjs +13 -3
- package/dist/client.mjs.map +1 -1
- package/dist/index.js +52 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +52 -4
- package/dist/index.mjs.map +1 -1
- package/dist/react.d.mts +64 -1
- package/dist/react.d.ts +64 -1
- package/dist/react.js +92 -26
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +92 -26
- package/dist/react.mjs.map +1 -1
- package/dist/svelte.d.mts +1 -1
- package/dist/svelte.d.ts +1 -1
- package/dist/svelte.js +13 -3
- package/dist/svelte.js.map +1 -1
- package/dist/svelte.mjs +13 -3
- package/dist/svelte.mjs.map +1 -1
- package/dist/vue.d.mts +1 -1
- package/dist/vue.d.ts +1 -1
- package/dist/vue.js +13 -3
- package/dist/vue.js.map +1 -1
- package/dist/vue.mjs +13 -3
- package/dist/vue.mjs.map +1 -1
- package/package.json +1 -1
package/dist/react.d.mts
CHANGED
|
@@ -265,12 +265,34 @@ interface AuthMethods {
|
|
|
265
265
|
* forms show it themselves.
|
|
266
266
|
*/
|
|
267
267
|
captchaSiteKey?: string;
|
|
268
|
+
/**
|
|
269
|
+
* Whether the workspace signs some people in through their company's SSO,
|
|
270
|
+
* found by their work address (`signIn.ssoDiscover`, `signIn.sso`).
|
|
271
|
+
*/
|
|
272
|
+
sso: boolean;
|
|
273
|
+
}
|
|
274
|
+
/** A company's sign-in (an SSO connection of the workspace). */
|
|
275
|
+
interface SSOConnection {
|
|
276
|
+
/** What `signIn.sso({ connection })` takes. */
|
|
277
|
+
id: string;
|
|
278
|
+
/** The company's name, for "Continue with …". */
|
|
279
|
+
name: string;
|
|
280
|
+
/** The address can sign in no other way: a password, link or provider answers `sso_required`. */
|
|
281
|
+
enforced: boolean;
|
|
268
282
|
}
|
|
283
|
+
/**
|
|
284
|
+
* What holds a passkey, as its authenticator says: a security key (a YubiKey),
|
|
285
|
+
* one synced across the person's devices (iCloud Keychain, Google Password
|
|
286
|
+
* Manager), one on a single device (Windows Hello), or unknown (made before
|
|
287
|
+
* Cauthy kept this).
|
|
288
|
+
*/
|
|
289
|
+
type PasskeyKind = 'security_key' | 'synced' | 'device' | 'unknown';
|
|
269
290
|
/** A passkey of the signed-in account. Moments are UTC. */
|
|
270
291
|
interface Passkey {
|
|
271
292
|
id: string;
|
|
272
293
|
/** What the person called it ("My laptop"), or "". */
|
|
273
294
|
name: string;
|
|
295
|
+
kind: PasskeyKind;
|
|
274
296
|
createdAt: string;
|
|
275
297
|
/** When it last signed the person in, or null. */
|
|
276
298
|
lastUsedAt: string | null;
|
|
@@ -444,10 +466,14 @@ interface AccountClient {
|
|
|
444
466
|
* Makes a passkey on this device, on this page: the browser asks the person
|
|
445
467
|
* for their fingerprint, face or screen lock. An account with a password
|
|
446
468
|
* proves it again first. `cancelled`: the person closed the browser's prompt.
|
|
469
|
+
* `kind` sends the browser straight to one: `'device'`, this device's
|
|
470
|
+
* fingerprint, face or screen lock; `'security_key'`, a security key.
|
|
471
|
+
* Without it, the browser offers all.
|
|
447
472
|
*/
|
|
448
473
|
addPasskey(form?: {
|
|
449
474
|
password?: string;
|
|
450
475
|
name?: string;
|
|
476
|
+
kind?: 'device' | 'security_key';
|
|
451
477
|
}): Promise<AuthResult<'added', {
|
|
452
478
|
passkey: Passkey;
|
|
453
479
|
}>>;
|
|
@@ -565,6 +591,38 @@ interface AuthClient {
|
|
|
565
591
|
social(provider: string, options?: {
|
|
566
592
|
returnTo?: string;
|
|
567
593
|
}): void;
|
|
594
|
+
/**
|
|
595
|
+
* Which company's sign-in a work address uses, if any (`found`), or
|
|
596
|
+
* `none`. It says so of the address's domain, never whether the address
|
|
597
|
+
* has an account.
|
|
598
|
+
*/
|
|
599
|
+
ssoDiscover(form: {
|
|
600
|
+
email: string;
|
|
601
|
+
}): Promise<AuthResult<'found', {
|
|
602
|
+
connection: SSOConnection;
|
|
603
|
+
}> | AuthResult<'none'>>;
|
|
604
|
+
/**
|
|
605
|
+
* Sends the browser to the person's company (found by `email`, or named
|
|
606
|
+
* by `connection`); it comes back signed in, at `returnTo`. A sign-in the
|
|
607
|
+
* company refused comes back with `?auth_error=`. Any other way of
|
|
608
|
+
* signing in answers `sso_required` for an address its company holds to
|
|
609
|
+
* SSO: send it here then.
|
|
610
|
+
*/
|
|
611
|
+
sso(target: {
|
|
612
|
+
email: string;
|
|
613
|
+
} | {
|
|
614
|
+
connection: string;
|
|
615
|
+
}, options?: {
|
|
616
|
+
returnTo?: string;
|
|
617
|
+
}): void;
|
|
618
|
+
/** Where `sso` sends the browser, for a plain link. */
|
|
619
|
+
ssoUrl(target: {
|
|
620
|
+
email: string;
|
|
621
|
+
} | {
|
|
622
|
+
connection: string;
|
|
623
|
+
}, options?: {
|
|
624
|
+
returnTo?: string;
|
|
625
|
+
}): string;
|
|
568
626
|
/** Where `social` sends the browser, for a plain link. */
|
|
569
627
|
socialUrl(provider: string, options?: {
|
|
570
628
|
returnTo?: string;
|
|
@@ -687,7 +745,11 @@ interface AuthTexts {
|
|
|
687
745
|
passkeysHelp: string;
|
|
688
746
|
noPasskeys: string;
|
|
689
747
|
passkeyName: string;
|
|
748
|
+
/** @deprecated Unused since 0.19.0: the account screen offers `addPasskeyDevice` and `addSecurityKey`. */
|
|
690
749
|
addPasskey: string;
|
|
750
|
+
addPasskeyDevice: string;
|
|
751
|
+
addSecurityKey: string;
|
|
752
|
+
passkeyKinds: Record<'security_key' | 'synced' | 'device', string>;
|
|
691
753
|
removePasskey: string;
|
|
692
754
|
passkeyAdded: string;
|
|
693
755
|
passkeyUnnamed: string;
|
|
@@ -707,6 +769,7 @@ interface AuthTexts {
|
|
|
707
769
|
linkWith: string;
|
|
708
770
|
unlink: string;
|
|
709
771
|
linked: string;
|
|
772
|
+
ssoOnly: string;
|
|
710
773
|
/** By error code; one missing shows what the server said. */
|
|
711
774
|
errors: Record<string, string>;
|
|
712
775
|
}
|
|
@@ -856,4 +919,4 @@ declare function useSession(): SessionContext;
|
|
|
856
919
|
*/
|
|
857
920
|
declare function useAuth(): AuthClient & Pick<SessionContext, 'session' | 'status' | 'refresh'>;
|
|
858
921
|
|
|
859
|
-
export { Account, type AccountClient, type Account$1 as AccountDetails, type AccountProps, type AccountSession, type AuthClient, type AuthError, type AuthFormProps, type AuthMethods, type AuthResult, type AuthTexts, CauthyProvider, type CauthyProviderProps, type ConnectedAgent, ForgotPassword, GoogleOneTap, type GoogleOneTapProps, type JsonValue, type LinkedIdentity, type Passkey, type PermissionOf, type Policy, type PublicSession, ResetPassword, type RoleOf, type SecondStep, type SessionContext, type SessionOrganization, type SessionUser, SignIn, SignUp, VerifyEmail, can, canAutofillPasskeys, canUsePasskeys, createAuthClient, definePolicy, useAuth, useSession };
|
|
922
|
+
export { Account, type AccountClient, type Account$1 as AccountDetails, type AccountProps, type AccountSession, type AuthClient, type AuthError, type AuthFormProps, type AuthMethods, type AuthResult, type AuthTexts, CauthyProvider, type CauthyProviderProps, type ConnectedAgent, ForgotPassword, GoogleOneTap, type GoogleOneTapProps, type JsonValue, type LinkedIdentity, type Passkey, type PasskeyKind, type PermissionOf, type Policy, type PublicSession, ResetPassword, type RoleOf, type SSOConnection, type SecondStep, type SessionContext, type SessionOrganization, type SessionUser, SignIn, SignUp, VerifyEmail, can, canAutofillPasskeys, canUsePasskeys, createAuthClient, definePolicy, useAuth, useSession };
|
package/dist/react.d.ts
CHANGED
|
@@ -265,12 +265,34 @@ interface AuthMethods {
|
|
|
265
265
|
* forms show it themselves.
|
|
266
266
|
*/
|
|
267
267
|
captchaSiteKey?: string;
|
|
268
|
+
/**
|
|
269
|
+
* Whether the workspace signs some people in through their company's SSO,
|
|
270
|
+
* found by their work address (`signIn.ssoDiscover`, `signIn.sso`).
|
|
271
|
+
*/
|
|
272
|
+
sso: boolean;
|
|
273
|
+
}
|
|
274
|
+
/** A company's sign-in (an SSO connection of the workspace). */
|
|
275
|
+
interface SSOConnection {
|
|
276
|
+
/** What `signIn.sso({ connection })` takes. */
|
|
277
|
+
id: string;
|
|
278
|
+
/** The company's name, for "Continue with …". */
|
|
279
|
+
name: string;
|
|
280
|
+
/** The address can sign in no other way: a password, link or provider answers `sso_required`. */
|
|
281
|
+
enforced: boolean;
|
|
268
282
|
}
|
|
283
|
+
/**
|
|
284
|
+
* What holds a passkey, as its authenticator says: a security key (a YubiKey),
|
|
285
|
+
* one synced across the person's devices (iCloud Keychain, Google Password
|
|
286
|
+
* Manager), one on a single device (Windows Hello), or unknown (made before
|
|
287
|
+
* Cauthy kept this).
|
|
288
|
+
*/
|
|
289
|
+
type PasskeyKind = 'security_key' | 'synced' | 'device' | 'unknown';
|
|
269
290
|
/** A passkey of the signed-in account. Moments are UTC. */
|
|
270
291
|
interface Passkey {
|
|
271
292
|
id: string;
|
|
272
293
|
/** What the person called it ("My laptop"), or "". */
|
|
273
294
|
name: string;
|
|
295
|
+
kind: PasskeyKind;
|
|
274
296
|
createdAt: string;
|
|
275
297
|
/** When it last signed the person in, or null. */
|
|
276
298
|
lastUsedAt: string | null;
|
|
@@ -444,10 +466,14 @@ interface AccountClient {
|
|
|
444
466
|
* Makes a passkey on this device, on this page: the browser asks the person
|
|
445
467
|
* for their fingerprint, face or screen lock. An account with a password
|
|
446
468
|
* proves it again first. `cancelled`: the person closed the browser's prompt.
|
|
469
|
+
* `kind` sends the browser straight to one: `'device'`, this device's
|
|
470
|
+
* fingerprint, face or screen lock; `'security_key'`, a security key.
|
|
471
|
+
* Without it, the browser offers all.
|
|
447
472
|
*/
|
|
448
473
|
addPasskey(form?: {
|
|
449
474
|
password?: string;
|
|
450
475
|
name?: string;
|
|
476
|
+
kind?: 'device' | 'security_key';
|
|
451
477
|
}): Promise<AuthResult<'added', {
|
|
452
478
|
passkey: Passkey;
|
|
453
479
|
}>>;
|
|
@@ -565,6 +591,38 @@ interface AuthClient {
|
|
|
565
591
|
social(provider: string, options?: {
|
|
566
592
|
returnTo?: string;
|
|
567
593
|
}): void;
|
|
594
|
+
/**
|
|
595
|
+
* Which company's sign-in a work address uses, if any (`found`), or
|
|
596
|
+
* `none`. It says so of the address's domain, never whether the address
|
|
597
|
+
* has an account.
|
|
598
|
+
*/
|
|
599
|
+
ssoDiscover(form: {
|
|
600
|
+
email: string;
|
|
601
|
+
}): Promise<AuthResult<'found', {
|
|
602
|
+
connection: SSOConnection;
|
|
603
|
+
}> | AuthResult<'none'>>;
|
|
604
|
+
/**
|
|
605
|
+
* Sends the browser to the person's company (found by `email`, or named
|
|
606
|
+
* by `connection`); it comes back signed in, at `returnTo`. A sign-in the
|
|
607
|
+
* company refused comes back with `?auth_error=`. Any other way of
|
|
608
|
+
* signing in answers `sso_required` for an address its company holds to
|
|
609
|
+
* SSO: send it here then.
|
|
610
|
+
*/
|
|
611
|
+
sso(target: {
|
|
612
|
+
email: string;
|
|
613
|
+
} | {
|
|
614
|
+
connection: string;
|
|
615
|
+
}, options?: {
|
|
616
|
+
returnTo?: string;
|
|
617
|
+
}): void;
|
|
618
|
+
/** Where `sso` sends the browser, for a plain link. */
|
|
619
|
+
ssoUrl(target: {
|
|
620
|
+
email: string;
|
|
621
|
+
} | {
|
|
622
|
+
connection: string;
|
|
623
|
+
}, options?: {
|
|
624
|
+
returnTo?: string;
|
|
625
|
+
}): string;
|
|
568
626
|
/** Where `social` sends the browser, for a plain link. */
|
|
569
627
|
socialUrl(provider: string, options?: {
|
|
570
628
|
returnTo?: string;
|
|
@@ -687,7 +745,11 @@ interface AuthTexts {
|
|
|
687
745
|
passkeysHelp: string;
|
|
688
746
|
noPasskeys: string;
|
|
689
747
|
passkeyName: string;
|
|
748
|
+
/** @deprecated Unused since 0.19.0: the account screen offers `addPasskeyDevice` and `addSecurityKey`. */
|
|
690
749
|
addPasskey: string;
|
|
750
|
+
addPasskeyDevice: string;
|
|
751
|
+
addSecurityKey: string;
|
|
752
|
+
passkeyKinds: Record<'security_key' | 'synced' | 'device', string>;
|
|
691
753
|
removePasskey: string;
|
|
692
754
|
passkeyAdded: string;
|
|
693
755
|
passkeyUnnamed: string;
|
|
@@ -707,6 +769,7 @@ interface AuthTexts {
|
|
|
707
769
|
linkWith: string;
|
|
708
770
|
unlink: string;
|
|
709
771
|
linked: string;
|
|
772
|
+
ssoOnly: string;
|
|
710
773
|
/** By error code; one missing shows what the server said. */
|
|
711
774
|
errors: Record<string, string>;
|
|
712
775
|
}
|
|
@@ -856,4 +919,4 @@ declare function useSession(): SessionContext;
|
|
|
856
919
|
*/
|
|
857
920
|
declare function useAuth(): AuthClient & Pick<SessionContext, 'session' | 'status' | 'refresh'>;
|
|
858
921
|
|
|
859
|
-
export { Account, type AccountClient, type Account$1 as AccountDetails, type AccountProps, type AccountSession, type AuthClient, type AuthError, type AuthFormProps, type AuthMethods, type AuthResult, type AuthTexts, CauthyProvider, type CauthyProviderProps, type ConnectedAgent, ForgotPassword, GoogleOneTap, type GoogleOneTapProps, type JsonValue, type LinkedIdentity, type Passkey, type PermissionOf, type Policy, type PublicSession, ResetPassword, type RoleOf, type SecondStep, type SessionContext, type SessionOrganization, type SessionUser, SignIn, SignUp, VerifyEmail, can, canAutofillPasskeys, canUsePasskeys, createAuthClient, definePolicy, useAuth, useSession };
|
|
922
|
+
export { Account, type AccountClient, type Account$1 as AccountDetails, type AccountProps, type AccountSession, type AuthClient, type AuthError, type AuthFormProps, type AuthMethods, type AuthResult, type AuthTexts, CauthyProvider, type CauthyProviderProps, type ConnectedAgent, ForgotPassword, GoogleOneTap, type GoogleOneTapProps, type JsonValue, type LinkedIdentity, type Passkey, type PasskeyKind, type PermissionOf, type Policy, type PublicSession, ResetPassword, type RoleOf, type SSOConnection, type SecondStep, type SessionContext, type SessionOrganization, type SessionUser, SignIn, SignUp, VerifyEmail, can, canAutofillPasskeys, canUsePasskeys, createAuthClient, definePolicy, useAuth, useSession };
|
package/dist/react.js
CHANGED
|
@@ -268,6 +268,11 @@ function createAuthClient(options = {}) {
|
|
|
268
268
|
}
|
|
269
269
|
const linkUrl = (provider, o = {}) => `${base}/me/identities/link/${encodeURIComponent(provider)}${o.returnTo ? `?return_to=${encodeURIComponent(o.returnTo)}` : ""}`;
|
|
270
270
|
const socialUrl = (provider, o = {}) => `${base}/sign-in/social/${encodeURIComponent(provider)}${o.returnTo ? `?return_to=${encodeURIComponent(o.returnTo)}` : ""}`;
|
|
271
|
+
const ssoUrl = (target, o = {}) => {
|
|
272
|
+
const q = new URLSearchParams("connection" in target ? { connection: target.connection } : { email: target.email.trim() });
|
|
273
|
+
if (o.returnTo) q.set("return_to", o.returnTo);
|
|
274
|
+
return `${base}/sign-in/sso?${q}`;
|
|
275
|
+
};
|
|
271
276
|
const passkeyUrl = (o = {}) => {
|
|
272
277
|
const q = new URLSearchParams({ method: "passkey" });
|
|
273
278
|
if (o.returnTo) q.set("return_to", o.returnTo);
|
|
@@ -279,11 +284,11 @@ function createAuthClient(options = {}) {
|
|
|
279
284
|
const res = await doFetch(`${base}/methods`, { credentials: "same-origin", headers: { accept: "application/json" } });
|
|
280
285
|
if (res.ok) {
|
|
281
286
|
const m = await res.json();
|
|
282
|
-
return { providers: [], signUp: true, magicLink: false, passkey: false, ...m, passkeyHere: m.passkeyHere === true, passkeyOnCauthy: m.passkeyOnCauthy ?? m.passkey === true };
|
|
287
|
+
return { providers: [], signUp: true, magicLink: false, passkey: false, ...m, passkeyHere: m.passkeyHere === true, passkeyOnCauthy: m.passkeyOnCauthy ?? m.passkey === true, sso: m.sso === true };
|
|
283
288
|
}
|
|
284
289
|
} catch {
|
|
285
290
|
}
|
|
286
|
-
return { providers: [], signUp: true, magicLink: false, passkey: false, passkeyHere: false, passkeyOnCauthy: false };
|
|
291
|
+
return { providers: [], signUp: true, magicLink: false, passkey: false, passkeyHere: false, passkeyOnCauthy: false, sso: false };
|
|
287
292
|
}
|
|
288
293
|
async function ceremony(begin, finish, form, run, more = {}) {
|
|
289
294
|
const begun = await post(begin, form, null);
|
|
@@ -381,6 +386,11 @@ function createAuthClient(options = {}) {
|
|
|
381
386
|
socialUrl,
|
|
382
387
|
social(provider, o) {
|
|
383
388
|
window.location.assign(socialUrl(provider, o));
|
|
389
|
+
},
|
|
390
|
+
ssoDiscover: (f) => post("/sign-in/sso/discover", { email: f.email.trim() }, checkEmail(f.email)),
|
|
391
|
+
ssoUrl,
|
|
392
|
+
sso(target, o) {
|
|
393
|
+
window.location.assign(ssoUrl(target, o));
|
|
384
394
|
}
|
|
385
395
|
},
|
|
386
396
|
signUp: {
|
|
@@ -439,7 +449,7 @@ function createAuthClient(options = {}) {
|
|
|
439
449
|
},
|
|
440
450
|
addPasskey(f = {}) {
|
|
441
451
|
if (!canUsePasskeys()) return Promise.resolve({ ok: false, error: { code: "passkey_unavailable", message: "This browser cannot make passkeys." } });
|
|
442
|
-
return ceremony("/me/passkeys/add/begin", "/me/passkeys/add/finish", { password: f.password ?? "" }, makePasskey, { name: f.name ?? "" });
|
|
452
|
+
return ceremony("/me/passkeys/add/begin", "/me/passkeys/add/finish", { password: f.password ?? "", ...f.kind ? { kind: f.kind } : {} }, makePasskey, { name: f.name ?? "" });
|
|
443
453
|
},
|
|
444
454
|
removePasskey: (id) => post("/me/passkeys/remove", { id }, null)
|
|
445
455
|
},
|
|
@@ -580,6 +590,9 @@ var TEXTS = {
|
|
|
580
590
|
passkeyName: "A name for this device (optional)",
|
|
581
591
|
addPasskey: "Add a passkey on this device",
|
|
582
592
|
removePasskey: "Remove",
|
|
593
|
+
addPasskeyDevice: "Add this device (fingerprint or face)",
|
|
594
|
+
addSecurityKey: "Add a security key",
|
|
595
|
+
passkeyKinds: { security_key: "Security key", synced: "Synced across your devices", device: "On this device only" },
|
|
583
596
|
passkeyAdded: "The passkey was added. Next time, sign in with it.",
|
|
584
597
|
passkeyUnnamed: "Passkey",
|
|
585
598
|
sessions: "Where you are signed in",
|
|
@@ -598,6 +611,7 @@ var TEXTS = {
|
|
|
598
611
|
linkWith: "Link",
|
|
599
612
|
unlink: "Unlink",
|
|
600
613
|
linked: "The account was linked.",
|
|
614
|
+
ssoOnly: "Your company signs you in to this account.",
|
|
601
615
|
errors: {
|
|
602
616
|
required: "This is required.",
|
|
603
617
|
invalid_email: "That does not look like an email address.",
|
|
@@ -626,7 +640,15 @@ var TEXTS = {
|
|
|
626
640
|
captcha_failed: "The check that you are not a bot did not pass. Try it again.",
|
|
627
641
|
passkey_failed: "The passkey could not be used. Try again, or sign in another way.",
|
|
628
642
|
passkey_exists: "This device already has a passkey for your account.",
|
|
629
|
-
passkey_unavailable: "Passkeys cannot be used here."
|
|
643
|
+
passkey_unavailable: "Passkeys cannot be used here.",
|
|
644
|
+
sso_required: "This address signs in through its company.",
|
|
645
|
+
sso_not_found: "No company sign-in answers for this address.",
|
|
646
|
+
sso_failed: "The sign-in with your company could not be completed. Try again.",
|
|
647
|
+
sso_unavailable: "Your company's sign-in cannot be reached right now. Try again in a moment.",
|
|
648
|
+
invalid_assertion: "Your company's answer could not be checked. Try again.",
|
|
649
|
+
provisioning_disabled: "Your company's sign-in worked, but this workspace has no account for you. Ask its admin to add you.",
|
|
650
|
+
connection_inactive: "Your company's sign-in is turned off for this workspace.",
|
|
651
|
+
invalid_grant: "That sign-in expired. Try again."
|
|
630
652
|
}
|
|
631
653
|
},
|
|
632
654
|
es: {
|
|
@@ -692,6 +714,9 @@ var TEXTS = {
|
|
|
692
714
|
passkeyName: "Un nombre para este dispositivo (opcional)",
|
|
693
715
|
addPasskey: "Agregar una llave en este dispositivo",
|
|
694
716
|
removePasskey: "Quitar",
|
|
717
|
+
addPasskeyDevice: "Agregar este dispositivo (huella o rostro)",
|
|
718
|
+
addSecurityKey: "Agregar una llave f\xEDsica",
|
|
719
|
+
passkeyKinds: { security_key: "Llave f\xEDsica", synced: "Sincronizada entre tus dispositivos", device: "Solo en un dispositivo" },
|
|
695
720
|
passkeyAdded: "La llave de acceso qued\xF3 agregada. La pr\xF3xima vez, entra con ella.",
|
|
696
721
|
passkeyUnnamed: "Llave de acceso",
|
|
697
722
|
sessions: "D\xF3nde tienes la sesi\xF3n abierta",
|
|
@@ -710,6 +735,7 @@ var TEXTS = {
|
|
|
710
735
|
linkWith: "Vincular",
|
|
711
736
|
unlink: "Desvincular",
|
|
712
737
|
linked: "La cuenta qued\xF3 vinculada.",
|
|
738
|
+
ssoOnly: "A esta cuenta entras con el inicio de sesi\xF3n de tu empresa.",
|
|
713
739
|
errors: {
|
|
714
740
|
required: "Este dato es obligatorio.",
|
|
715
741
|
invalid_email: "Eso no parece un correo.",
|
|
@@ -738,7 +764,15 @@ var TEXTS = {
|
|
|
738
764
|
captcha_failed: "La verificaci\xF3n de que no eres un robot no pas\xF3. Int\xE9ntalo de nuevo.",
|
|
739
765
|
passkey_failed: "No se pudo usar la llave de acceso. Intenta de nuevo o entra de otra forma.",
|
|
740
766
|
passkey_exists: "Este dispositivo ya tiene una llave de acceso de tu cuenta.",
|
|
741
|
-
passkey_unavailable: "Aqu\xED no se pueden usar llaves de acceso."
|
|
767
|
+
passkey_unavailable: "Aqu\xED no se pueden usar llaves de acceso.",
|
|
768
|
+
sso_required: "Este correo entra con el inicio de sesi\xF3n de su empresa.",
|
|
769
|
+
sso_not_found: "Ninguna empresa usa inicio de sesi\xF3n propio con este correo.",
|
|
770
|
+
sso_failed: "No se pudo completar el ingreso con tu empresa. Intenta de nuevo.",
|
|
771
|
+
sso_unavailable: "Ahora no se puede llegar al inicio de sesi\xF3n de tu empresa. Intenta en un momento.",
|
|
772
|
+
invalid_assertion: "No se pudo verificar la respuesta de tu empresa. Intenta de nuevo.",
|
|
773
|
+
provisioning_disabled: "El ingreso con tu empresa funcion\xF3, pero este workspace no tiene una cuenta para ti. P\xEDdele a su admin que te agregue.",
|
|
774
|
+
connection_inactive: "El inicio de sesi\xF3n de tu empresa est\xE1 apagado en este workspace.",
|
|
775
|
+
invalid_grant: "Ese ingreso venci\xF3. Intenta de nuevo."
|
|
742
776
|
}
|
|
743
777
|
}
|
|
744
778
|
};
|
|
@@ -931,6 +965,25 @@ function SignIn(props) {
|
|
|
931
965
|
};
|
|
932
966
|
const autofill = (0, import_react.useRef)(null);
|
|
933
967
|
const [offer, setOffer] = (0, import_react.useState)(0);
|
|
968
|
+
const [company, setCompany] = (0, import_react.useState)(null);
|
|
969
|
+
(0, import_react.useEffect)(() => {
|
|
970
|
+
if (!methods?.sso || checkEmail(email) !== null) return setCompany(null);
|
|
971
|
+
let current = true;
|
|
972
|
+
const t = setTimeout(() => {
|
|
973
|
+
void auth.signIn.ssoDiscover({ email }).then((r) => {
|
|
974
|
+
if (current) setCompany(r.ok && r.status === "found" ? r.connection : null);
|
|
975
|
+
});
|
|
976
|
+
}, 350);
|
|
977
|
+
return () => {
|
|
978
|
+
current = false;
|
|
979
|
+
clearTimeout(t);
|
|
980
|
+
};
|
|
981
|
+
}, [email, methods]);
|
|
982
|
+
const toCompany = () => {
|
|
983
|
+
autofill.current?.abort();
|
|
984
|
+
f.setBusy(true);
|
|
985
|
+
auth.signIn.sso({ email }, { returnTo: props.returnTo });
|
|
986
|
+
};
|
|
934
987
|
(0, import_react.useEffect)(() => {
|
|
935
988
|
void auth.methods().then(setMethods);
|
|
936
989
|
const back = returnedError();
|
|
@@ -963,9 +1016,11 @@ function SignIn(props) {
|
|
|
963
1016
|
autofill.current?.abort();
|
|
964
1017
|
f.setBusy(true);
|
|
965
1018
|
f.setError(null);
|
|
1019
|
+
if (step === "password" && company?.enforced) return toCompany();
|
|
966
1020
|
const r = step === "code" ? await auth.signIn.mfa({ code }) : step === "sent" ? await auth.signIn.emailCode({ code }) : await auth.signIn.email({ email, password, captchaToken: challenge.token });
|
|
967
1021
|
f.setBusy(false);
|
|
968
1022
|
if (step === "password") challenge.renew();
|
|
1023
|
+
if (!r.ok && r.error.code === "sso_required") return toCompany();
|
|
969
1024
|
if (!r.ok) {
|
|
970
1025
|
setOffer((n) => n + 1);
|
|
971
1026
|
return f.setError(r.error);
|
|
@@ -991,6 +1046,7 @@ function SignIn(props) {
|
|
|
991
1046
|
const r = await auth.signIn.magicLink({ email, captchaToken: challenge.token, create: props.createAccounts, returnTo: props.returnTo });
|
|
992
1047
|
f.setBusy(false);
|
|
993
1048
|
challenge.renew();
|
|
1049
|
+
if (!r.ok && r.error.code === "sso_required") return toCompany();
|
|
994
1050
|
if (!r.ok) return f.setError(r.error);
|
|
995
1051
|
setStep("sent");
|
|
996
1052
|
};
|
|
@@ -1025,23 +1081,31 @@ function SignIn(props) {
|
|
|
1025
1081
|
methods?.passkey && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void usePasskey(), children: f.t.usePasskey }),
|
|
1026
1082
|
((methods?.providers.length ?? 0) > 0 || methods?.passkey) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: f.cx("separator"), children: f.t.orWithEmail }),
|
|
1027
1083
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "email", type: "email", label: f.t.email, value: email, autoComplete: methods?.passkeyHere ? "username webauthn" : "username", required: true, onChange: setEmail }),
|
|
1028
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1084
|
+
company && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(f.Button, { type: "button", disabled: f.busy, className: f.cx(company.enforced ? "button" : "providerButton"), onClick: toCompany, children: [
|
|
1085
|
+
f.t.continueWith,
|
|
1086
|
+
" ",
|
|
1087
|
+
company.name
|
|
1088
|
+
] }),
|
|
1089
|
+
company?.enforced && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: f.cx("notice"), children: f.t.ssoOnly }),
|
|
1090
|
+
!company?.enforced && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1091
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1092
|
+
Field,
|
|
1093
|
+
{
|
|
1094
|
+
f,
|
|
1095
|
+
name: "password",
|
|
1096
|
+
type: "password",
|
|
1097
|
+
label: f.t.password,
|
|
1098
|
+
value: password,
|
|
1099
|
+
autoComplete: "current-password",
|
|
1100
|
+
required: true,
|
|
1101
|
+
onChange: setPassword,
|
|
1102
|
+
aside: props.links?.forgotPassword ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { className: f.cx("link"), href: props.links.forgotPassword, children: f.t.forgotPassword }) : void 0
|
|
1103
|
+
}
|
|
1104
|
+
),
|
|
1105
|
+
challenge.node,
|
|
1106
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.signIn })
|
|
1107
|
+
] }),
|
|
1108
|
+
methods?.magicLink && !company?.enforced && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void sendLink(), children: f.t.emailMeALink }),
|
|
1045
1109
|
methods?.signUp !== false && props.links?.signUp && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: f.cx("footer"), children: [
|
|
1046
1110
|
f.t.noAccount,
|
|
1047
1111
|
" ",
|
|
@@ -1267,9 +1331,9 @@ function PasskeysPart({ props, account, accountUrl, when }) {
|
|
|
1267
1331
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { className: f.cx("link"), href: accountUrl, children: f.t.managePasskeys })
|
|
1268
1332
|
] });
|
|
1269
1333
|
}
|
|
1270
|
-
const add = async (e) => {
|
|
1271
|
-
e
|
|
1272
|
-
const r = await run(() => auth.account.addPasskey({ name, password }));
|
|
1334
|
+
const add = async (e, kind = "device") => {
|
|
1335
|
+
e?.preventDefault();
|
|
1336
|
+
const r = await run(() => auth.account.addPasskey({ name, password, kind }));
|
|
1273
1337
|
if (!r.ok) {
|
|
1274
1338
|
if (r.error.code === "cancelled") f.setError(null);
|
|
1275
1339
|
return;
|
|
@@ -1289,6 +1353,7 @@ function PasskeysPart({ props, account, accountUrl, when }) {
|
|
|
1289
1353
|
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "alert", className: f.cx("error"), children: f.say(general) }),
|
|
1290
1354
|
list.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: f.cx("notice"), children: f.t.noPasskeys }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: f.cx("sessions"), children: list.map((p) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { className: f.cx("session"), children: [
|
|
1291
1355
|
p.name || f.t.passkeyUnnamed,
|
|
1356
|
+
p.kind !== "unknown" ? ` \xB7 ${f.t.passkeyKinds[p.kind]}` : "",
|
|
1292
1357
|
" \xB7 ",
|
|
1293
1358
|
when(p.createdAt),
|
|
1294
1359
|
" ",
|
|
@@ -1296,7 +1361,8 @@ function PasskeysPart({ props, account, accountUrl, when }) {
|
|
|
1296
1361
|
] }, p.id)) }),
|
|
1297
1362
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "name", type: "text", label: f.t.passkeyName, value: name, autoComplete: "off", onChange: setName }),
|
|
1298
1363
|
account.hasPassword && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "password", type: "password", label: f.t.currentPassword, value: password, autoComplete: "current-password", required: true, onChange: setPassword }),
|
|
1299
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.
|
|
1364
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.addPasskeyDevice }),
|
|
1365
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void add(null, "security_key"), children: f.t.addSecurityKey }),
|
|
1300
1366
|
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "status", className: f.cx("notice"), children: done })
|
|
1301
1367
|
] });
|
|
1302
1368
|
}
|