cauthy-auth 0.9.0 → 0.11.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 +61 -5
- package/dist/client.d.ts +61 -5
- package/dist/client.js +118 -12
- package/dist/client.js.map +1 -1
- package/dist/client.mjs +117 -12
- package/dist/client.mjs.map +1 -1
- package/dist/index.js +121 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +121 -6
- package/dist/index.mjs.map +1 -1
- package/dist/react.d.mts +68 -5
- package/dist/react.d.ts +68 -5
- package/dist/react.js +203 -18
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +202 -18
- 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 +116 -12
- package/dist/svelte.js.map +1 -1
- package/dist/svelte.mjs +116 -12
- 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 +116 -12
- package/dist/vue.js.map +1 -1
- package/dist/vue.mjs +116 -12
- package/dist/vue.mjs.map +1 -1
- package/package.json +1 -1
package/dist/client.d.mts
CHANGED
|
@@ -4,6 +4,9 @@ import { A as AuthField } from './validate-B_iC-4y8.mjs';
|
|
|
4
4
|
export { F as FieldProblem, M as MIN_PASSWORD, c as checkCode, a as checkEmail, b as checkName, d as checkNewPassword, e as checkPassword } from './validate-B_iC-4y8.mjs';
|
|
5
5
|
import 'jose';
|
|
6
6
|
|
|
7
|
+
/** Whether this browser can use a passkey at all. */
|
|
8
|
+
declare function canUsePasskeys(): boolean;
|
|
9
|
+
|
|
7
10
|
interface SessionState {
|
|
8
11
|
/** The signed-in person and their organizations, or null. */
|
|
9
12
|
session: PublicSession | null;
|
|
@@ -70,8 +73,29 @@ interface AuthMethods {
|
|
|
70
73
|
/** Whether people may create an account themselves. */
|
|
71
74
|
signUp: boolean;
|
|
72
75
|
magicLink: boolean;
|
|
73
|
-
/** Whether to offer a passkey.
|
|
76
|
+
/** Whether to offer a passkey. */
|
|
74
77
|
passkey: boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Whether the passkey is used on this page itself. False: `signIn.passkey`
|
|
80
|
+
* sends the person to Cauthy's page for that step alone, and they come back
|
|
81
|
+
* signed in. That happens only when this page is outside the domain the
|
|
82
|
+
* workspace's passkeys belong to.
|
|
83
|
+
*/
|
|
84
|
+
passkeyHere: boolean;
|
|
85
|
+
/**
|
|
86
|
+
* Whether Cauthy's page can use the passkey, for that step alone: where a
|
|
87
|
+
* page that cannot, or a browser that refuses to here, sends the person.
|
|
88
|
+
*/
|
|
89
|
+
passkeyOnCauthy: boolean;
|
|
90
|
+
}
|
|
91
|
+
/** A passkey of the signed-in account. Moments are UTC. */
|
|
92
|
+
interface Passkey {
|
|
93
|
+
id: string;
|
|
94
|
+
/** What the person called it ("My laptop"), or "". */
|
|
95
|
+
name: string;
|
|
96
|
+
createdAt: string;
|
|
97
|
+
/** When it last signed the person in, or null. */
|
|
98
|
+
lastUsedAt: string | null;
|
|
75
99
|
}
|
|
76
100
|
/** A person's own account, as their account screen shows it. */
|
|
77
101
|
interface Account {
|
|
@@ -175,6 +199,22 @@ interface AccountClient {
|
|
|
175
199
|
sessions(): Promise<AccountSession[]>;
|
|
176
200
|
/** Signs the account out everywhere, here too. */
|
|
177
201
|
signOutEverywhere(): Promise<AuthResult<'signed_out'>>;
|
|
202
|
+
/** The account's passkeys. */
|
|
203
|
+
passkeys(): Promise<Passkey[]>;
|
|
204
|
+
/**
|
|
205
|
+
* Makes a passkey on this device, on this page: the browser asks the person
|
|
206
|
+
* for their fingerprint, face or screen lock. An account with a password
|
|
207
|
+
* proves it again first. `cancelled`: the person closed the browser's prompt.
|
|
208
|
+
*/
|
|
209
|
+
addPasskey(form?: {
|
|
210
|
+
password?: string;
|
|
211
|
+
name?: string;
|
|
212
|
+
}): Promise<AuthResult<'added', {
|
|
213
|
+
passkey: Passkey;
|
|
214
|
+
}>>;
|
|
215
|
+
removePasskey(id: string): Promise<AuthResult<'removed', {
|
|
216
|
+
id: string;
|
|
217
|
+
}>>;
|
|
178
218
|
}
|
|
179
219
|
interface AuthClient {
|
|
180
220
|
signIn: {
|
|
@@ -207,12 +247,21 @@ interface AuthClient {
|
|
|
207
247
|
}): Promise<AuthResult<'signed_in', {
|
|
208
248
|
session: PublicSession;
|
|
209
249
|
}>>;
|
|
210
|
-
/**
|
|
250
|
+
/**
|
|
251
|
+
* Signs in with a passkey, on this page: the browser asks the person for
|
|
252
|
+
* their fingerprint, face or screen lock. When this page cannot use the
|
|
253
|
+
* workspace's passkeys (`methods().passkeyHere` is false), the browser goes
|
|
254
|
+
* to Cauthy's page for that step alone and comes back signed in, at
|
|
255
|
+
* `returnTo`: then the answer is `redirected`. `cancelled`: the person
|
|
256
|
+
* closed the browser's prompt.
|
|
257
|
+
*/
|
|
211
258
|
passkey(options?: {
|
|
212
259
|
returnTo?: string;
|
|
213
260
|
locale?: string;
|
|
214
|
-
}):
|
|
215
|
-
|
|
261
|
+
}): Promise<AuthResult<'signed_in', {
|
|
262
|
+
session: PublicSession;
|
|
263
|
+
}> | AuthResult<'redirected'>>;
|
|
264
|
+
/** Where `passkey` sends the browser when this page cannot use the passkey itself. */
|
|
216
265
|
passkeyUrl(options?: {
|
|
217
266
|
returnTo?: string;
|
|
218
267
|
locale?: string;
|
|
@@ -267,7 +316,14 @@ interface AuthClientOptions {
|
|
|
267
316
|
/** Where the server mounted the routes. Default: `/api/auth`. */
|
|
268
317
|
basePath?: string;
|
|
269
318
|
fetch?: typeof fetch;
|
|
319
|
+
/**
|
|
320
|
+
* The language the person reads, for what Cauthy mails them (a sign-in
|
|
321
|
+
* link, a new password, a confirmation): a tag like `es` or `es-CO`, or a
|
|
322
|
+
* function that answers it when the person can change it. Default: the
|
|
323
|
+
* page's own (`<html lang>`), else the browser's.
|
|
324
|
+
*/
|
|
325
|
+
locale?: string | (() => string | undefined);
|
|
270
326
|
}
|
|
271
327
|
declare function createAuthClient(options?: AuthClientOptions): AuthClient;
|
|
272
328
|
|
|
273
|
-
export { type Account, type AccountClient, type AccountSession, type AuthClient, type AuthClientOptions, type AuthError, AuthField, type AuthMethods, type AuthResult, type LinkedIdentity, type SessionState, type SessionStore, type SessionStoreOptions, createAuthClient, createSessionStore };
|
|
329
|
+
export { type Account, type AccountClient, type AccountSession, type AuthClient, type AuthClientOptions, type AuthError, AuthField, type AuthMethods, type AuthResult, type LinkedIdentity, type Passkey, type SessionState, type SessionStore, type SessionStoreOptions, canUsePasskeys, createAuthClient, createSessionStore };
|
package/dist/client.d.ts
CHANGED
|
@@ -4,6 +4,9 @@ import { A as AuthField } from './validate-B_iC-4y8.js';
|
|
|
4
4
|
export { F as FieldProblem, M as MIN_PASSWORD, c as checkCode, a as checkEmail, b as checkName, d as checkNewPassword, e as checkPassword } from './validate-B_iC-4y8.js';
|
|
5
5
|
import 'jose';
|
|
6
6
|
|
|
7
|
+
/** Whether this browser can use a passkey at all. */
|
|
8
|
+
declare function canUsePasskeys(): boolean;
|
|
9
|
+
|
|
7
10
|
interface SessionState {
|
|
8
11
|
/** The signed-in person and their organizations, or null. */
|
|
9
12
|
session: PublicSession | null;
|
|
@@ -70,8 +73,29 @@ interface AuthMethods {
|
|
|
70
73
|
/** Whether people may create an account themselves. */
|
|
71
74
|
signUp: boolean;
|
|
72
75
|
magicLink: boolean;
|
|
73
|
-
/** Whether to offer a passkey.
|
|
76
|
+
/** Whether to offer a passkey. */
|
|
74
77
|
passkey: boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Whether the passkey is used on this page itself. False: `signIn.passkey`
|
|
80
|
+
* sends the person to Cauthy's page for that step alone, and they come back
|
|
81
|
+
* signed in. That happens only when this page is outside the domain the
|
|
82
|
+
* workspace's passkeys belong to.
|
|
83
|
+
*/
|
|
84
|
+
passkeyHere: boolean;
|
|
85
|
+
/**
|
|
86
|
+
* Whether Cauthy's page can use the passkey, for that step alone: where a
|
|
87
|
+
* page that cannot, or a browser that refuses to here, sends the person.
|
|
88
|
+
*/
|
|
89
|
+
passkeyOnCauthy: boolean;
|
|
90
|
+
}
|
|
91
|
+
/** A passkey of the signed-in account. Moments are UTC. */
|
|
92
|
+
interface Passkey {
|
|
93
|
+
id: string;
|
|
94
|
+
/** What the person called it ("My laptop"), or "". */
|
|
95
|
+
name: string;
|
|
96
|
+
createdAt: string;
|
|
97
|
+
/** When it last signed the person in, or null. */
|
|
98
|
+
lastUsedAt: string | null;
|
|
75
99
|
}
|
|
76
100
|
/** A person's own account, as their account screen shows it. */
|
|
77
101
|
interface Account {
|
|
@@ -175,6 +199,22 @@ interface AccountClient {
|
|
|
175
199
|
sessions(): Promise<AccountSession[]>;
|
|
176
200
|
/** Signs the account out everywhere, here too. */
|
|
177
201
|
signOutEverywhere(): Promise<AuthResult<'signed_out'>>;
|
|
202
|
+
/** The account's passkeys. */
|
|
203
|
+
passkeys(): Promise<Passkey[]>;
|
|
204
|
+
/**
|
|
205
|
+
* Makes a passkey on this device, on this page: the browser asks the person
|
|
206
|
+
* for their fingerprint, face or screen lock. An account with a password
|
|
207
|
+
* proves it again first. `cancelled`: the person closed the browser's prompt.
|
|
208
|
+
*/
|
|
209
|
+
addPasskey(form?: {
|
|
210
|
+
password?: string;
|
|
211
|
+
name?: string;
|
|
212
|
+
}): Promise<AuthResult<'added', {
|
|
213
|
+
passkey: Passkey;
|
|
214
|
+
}>>;
|
|
215
|
+
removePasskey(id: string): Promise<AuthResult<'removed', {
|
|
216
|
+
id: string;
|
|
217
|
+
}>>;
|
|
178
218
|
}
|
|
179
219
|
interface AuthClient {
|
|
180
220
|
signIn: {
|
|
@@ -207,12 +247,21 @@ interface AuthClient {
|
|
|
207
247
|
}): Promise<AuthResult<'signed_in', {
|
|
208
248
|
session: PublicSession;
|
|
209
249
|
}>>;
|
|
210
|
-
/**
|
|
250
|
+
/**
|
|
251
|
+
* Signs in with a passkey, on this page: the browser asks the person for
|
|
252
|
+
* their fingerprint, face or screen lock. When this page cannot use the
|
|
253
|
+
* workspace's passkeys (`methods().passkeyHere` is false), the browser goes
|
|
254
|
+
* to Cauthy's page for that step alone and comes back signed in, at
|
|
255
|
+
* `returnTo`: then the answer is `redirected`. `cancelled`: the person
|
|
256
|
+
* closed the browser's prompt.
|
|
257
|
+
*/
|
|
211
258
|
passkey(options?: {
|
|
212
259
|
returnTo?: string;
|
|
213
260
|
locale?: string;
|
|
214
|
-
}):
|
|
215
|
-
|
|
261
|
+
}): Promise<AuthResult<'signed_in', {
|
|
262
|
+
session: PublicSession;
|
|
263
|
+
}> | AuthResult<'redirected'>>;
|
|
264
|
+
/** Where `passkey` sends the browser when this page cannot use the passkey itself. */
|
|
216
265
|
passkeyUrl(options?: {
|
|
217
266
|
returnTo?: string;
|
|
218
267
|
locale?: string;
|
|
@@ -267,7 +316,14 @@ interface AuthClientOptions {
|
|
|
267
316
|
/** Where the server mounted the routes. Default: `/api/auth`. */
|
|
268
317
|
basePath?: string;
|
|
269
318
|
fetch?: typeof fetch;
|
|
319
|
+
/**
|
|
320
|
+
* The language the person reads, for what Cauthy mails them (a sign-in
|
|
321
|
+
* link, a new password, a confirmation): a tag like `es` or `es-CO`, or a
|
|
322
|
+
* function that answers it when the person can change it. Default: the
|
|
323
|
+
* page's own (`<html lang>`), else the browser's.
|
|
324
|
+
*/
|
|
325
|
+
locale?: string | (() => string | undefined);
|
|
270
326
|
}
|
|
271
327
|
declare function createAuthClient(options?: AuthClientOptions): AuthClient;
|
|
272
328
|
|
|
273
|
-
export { type Account, type AccountClient, type AccountSession, type AuthClient, type AuthClientOptions, type AuthError, AuthField, type AuthMethods, type AuthResult, type LinkedIdentity, type SessionState, type SessionStore, type SessionStoreOptions, createAuthClient, createSessionStore };
|
|
329
|
+
export { type Account, type AccountClient, type AccountSession, type AuthClient, type AuthClientOptions, type AuthError, AuthField, type AuthMethods, type AuthResult, type LinkedIdentity, type Passkey, type SessionState, type SessionStore, type SessionStoreOptions, canUsePasskeys, createAuthClient, createSessionStore };
|
package/dist/client.js
CHANGED
|
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var client_exports = {};
|
|
22
22
|
__export(client_exports, {
|
|
23
23
|
MIN_PASSWORD: () => MIN_PASSWORD,
|
|
24
|
+
canUsePasskeys: () => canUsePasskeys,
|
|
24
25
|
checkCode: () => checkCode,
|
|
25
26
|
checkEmail: () => checkEmail,
|
|
26
27
|
checkName: () => checkName,
|
|
@@ -31,6 +32,73 @@ __export(client_exports, {
|
|
|
31
32
|
});
|
|
32
33
|
module.exports = __toCommonJS(client_exports);
|
|
33
34
|
|
|
35
|
+
// src/passkey.ts
|
|
36
|
+
function canUsePasskeys() {
|
|
37
|
+
return typeof window !== "undefined" && typeof window.PublicKeyCredential === "function" && typeof navigator !== "undefined" && typeof navigator.credentials?.get === "function";
|
|
38
|
+
}
|
|
39
|
+
function bytes(text2) {
|
|
40
|
+
const b64 = text2.replace(/-/g, "+").replace(/_/g, "/").padEnd(Math.ceil(text2.length / 4) * 4, "=");
|
|
41
|
+
const bin = atob(b64);
|
|
42
|
+
const out = new Uint8Array(bin.length);
|
|
43
|
+
for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
|
|
44
|
+
return out.buffer;
|
|
45
|
+
}
|
|
46
|
+
function text(buf) {
|
|
47
|
+
if (!buf) return null;
|
|
48
|
+
const view = new Uint8Array(buf);
|
|
49
|
+
let bin = "";
|
|
50
|
+
for (let i = 0; i < view.byteLength; i++) bin += String.fromCharCode(view[i]);
|
|
51
|
+
return btoa(bin).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
52
|
+
}
|
|
53
|
+
var withId = (list) => (list ?? []).map((c) => ({ ...c, id: bytes(c.id) }));
|
|
54
|
+
async function getPasskey(options) {
|
|
55
|
+
const publicKey = { ...options, challenge: bytes(options.challenge), allowCredentials: withId(options.allowCredentials) };
|
|
56
|
+
const cred = await navigator.credentials.get({ publicKey });
|
|
57
|
+
if (cred === null) throw new DOMException("No passkey was chosen.", "NotAllowedError");
|
|
58
|
+
const r = cred.response;
|
|
59
|
+
return {
|
|
60
|
+
id: cred.id,
|
|
61
|
+
rawId: text(cred.rawId),
|
|
62
|
+
type: cred.type,
|
|
63
|
+
response: {
|
|
64
|
+
authenticatorData: text(r.authenticatorData),
|
|
65
|
+
clientDataJSON: text(r.clientDataJSON),
|
|
66
|
+
signature: text(r.signature),
|
|
67
|
+
userHandle: text(r.userHandle)
|
|
68
|
+
},
|
|
69
|
+
clientExtensionResults: cred.getClientExtensionResults?.() ?? {}
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
async function makePasskey(options) {
|
|
73
|
+
const publicKey = {
|
|
74
|
+
...options,
|
|
75
|
+
challenge: bytes(options.challenge),
|
|
76
|
+
user: { ...options.user, id: bytes(options.user.id) },
|
|
77
|
+
excludeCredentials: withId(options.excludeCredentials)
|
|
78
|
+
};
|
|
79
|
+
const cred = await navigator.credentials.create({ publicKey });
|
|
80
|
+
if (cred === null) throw new DOMException("No passkey was made.", "NotAllowedError");
|
|
81
|
+
const r = cred.response;
|
|
82
|
+
return {
|
|
83
|
+
id: cred.id,
|
|
84
|
+
rawId: text(cred.rawId),
|
|
85
|
+
type: cred.type,
|
|
86
|
+
response: {
|
|
87
|
+
clientDataJSON: text(r.clientDataJSON),
|
|
88
|
+
attestationObject: text(r.attestationObject),
|
|
89
|
+
transports: typeof r.getTransports === "function" ? r.getTransports() : []
|
|
90
|
+
},
|
|
91
|
+
clientExtensionResults: cred.getClientExtensionResults?.() ?? {}
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function ceremonyError(e) {
|
|
95
|
+
const name = e instanceof Error || e instanceof DOMException ? e.name : "";
|
|
96
|
+
if (name === "NotAllowedError" || name === "AbortError") return { code: "cancelled", message: "The passkey was not used. Try again when you are ready." };
|
|
97
|
+
if (name === "InvalidStateError") return { code: "passkey_exists", message: "This device already has a passkey for this account." };
|
|
98
|
+
if (name === "SecurityError") return { code: "passkey_unavailable", message: "Passkeys cannot be used on this page." };
|
|
99
|
+
return { code: "passkey_failed", message: "The passkey could not be used. Try again, or sign in another way." };
|
|
100
|
+
}
|
|
101
|
+
|
|
34
102
|
// src/theme.ts
|
|
35
103
|
function fromWire(wire) {
|
|
36
104
|
const names = {
|
|
@@ -196,7 +264,8 @@ function createSessionStore(options = {}) {
|
|
|
196
264
|
email: (f) => then(client.signIn.email(f)),
|
|
197
265
|
mfa: (f) => then(client.signIn.mfa(f)),
|
|
198
266
|
magicLinkVerify: (f) => then(client.signIn.magicLinkVerify(f)),
|
|
199
|
-
emailCode: (f) => then(client.signIn.emailCode(f))
|
|
267
|
+
emailCode: (f) => then(client.signIn.emailCode(f)),
|
|
268
|
+
passkey: (o) => then(client.signIn.passkey(o))
|
|
200
269
|
},
|
|
201
270
|
signUp: { email: (f) => then(client.signUp.email(f)) },
|
|
202
271
|
signOut: () => then(client.signOut()),
|
|
@@ -216,13 +285,17 @@ var UNAVAILABLE = { code: "unavailable", message: "Sign-in is unavailable right
|
|
|
216
285
|
function createAuthClient(options = {}) {
|
|
217
286
|
const base = (options.basePath ?? "/api/auth").replace(/\/+$/, "");
|
|
218
287
|
const doFetch = (...args) => (options.fetch ?? fetch)(...args);
|
|
288
|
+
const locale = () => {
|
|
289
|
+
const said = typeof options.locale === "function" ? options.locale() : options.locale;
|
|
290
|
+
return (said ?? (typeof document === "undefined" ? "" : document.documentElement?.lang) ?? "").trim();
|
|
291
|
+
};
|
|
219
292
|
async function post(path, form, bad) {
|
|
220
293
|
if (bad) return { ok: false, error: { code: bad.code, message: bad.message, field: bad.field } };
|
|
221
294
|
try {
|
|
222
295
|
const res = await doFetch(`${base}${path}`, {
|
|
223
296
|
method: "POST",
|
|
224
297
|
credentials: "same-origin",
|
|
225
|
-
headers: { "content-type": "application/json", accept: "application/json" },
|
|
298
|
+
headers: { "content-type": "application/json", accept: "application/json", ...locale() ? { "x-cauthy-locale": locale() } : {} },
|
|
226
299
|
body: JSON.stringify(form)
|
|
227
300
|
});
|
|
228
301
|
const body = await res.json().catch(() => null);
|
|
@@ -250,6 +323,28 @@ function createAuthClient(options = {}) {
|
|
|
250
323
|
if (o.locale) q.set("locale", o.locale);
|
|
251
324
|
return `${base}/login?${q}`;
|
|
252
325
|
};
|
|
326
|
+
async function methods() {
|
|
327
|
+
try {
|
|
328
|
+
const res = await doFetch(`${base}/methods`, { credentials: "same-origin", headers: { accept: "application/json" } });
|
|
329
|
+
if (res.ok) {
|
|
330
|
+
const m = await res.json();
|
|
331
|
+
return { providers: [], signUp: true, magicLink: false, passkey: false, ...m, passkeyHere: m.passkeyHere === true, passkeyOnCauthy: m.passkeyOnCauthy ?? m.passkey === true };
|
|
332
|
+
}
|
|
333
|
+
} catch {
|
|
334
|
+
}
|
|
335
|
+
return { providers: [], signUp: true, magicLink: false, passkey: false, passkeyHere: false, passkeyOnCauthy: false };
|
|
336
|
+
}
|
|
337
|
+
async function ceremony(begin, finish, form, run, more = {}) {
|
|
338
|
+
const begun = await post(begin, form, null);
|
|
339
|
+
if (!begun.ok) return begun;
|
|
340
|
+
let credential;
|
|
341
|
+
try {
|
|
342
|
+
credential = await run(begun.options);
|
|
343
|
+
} catch (e) {
|
|
344
|
+
return { ok: false, error: ceremonyError(e) };
|
|
345
|
+
}
|
|
346
|
+
return post(finish, { credential, ...more }, null);
|
|
347
|
+
}
|
|
253
348
|
return {
|
|
254
349
|
signIn: {
|
|
255
350
|
email: (f) => post("/sign-in/email", { email: f.email, password: f.password }, firstProblem(checkEmail(f.email), checkPassword(f.password))),
|
|
@@ -258,8 +353,16 @@ function createAuthClient(options = {}) {
|
|
|
258
353
|
magicLinkVerify: (f) => post("/sign-in/magic-link/verify", { token: f.token }, null),
|
|
259
354
|
emailCode: (f) => post("/sign-in/email-code", { code: f.code }, checkCode(f.code)),
|
|
260
355
|
passkeyUrl,
|
|
261
|
-
passkey(o) {
|
|
356
|
+
async passkey(o) {
|
|
357
|
+
const m = await methods();
|
|
358
|
+
if (m.passkeyHere && canUsePasskeys()) {
|
|
359
|
+
const r = await ceremony("/sign-in/passkey/begin", "/sign-in/passkey/finish", {}, getPasskey);
|
|
360
|
+
if (r.ok || r.error.code !== "passkey_unavailable" || !m.passkeyOnCauthy) return r;
|
|
361
|
+
} else if (!m.passkeyOnCauthy) {
|
|
362
|
+
return { ok: false, error: { code: "passkey_unavailable", message: "Passkeys cannot be used here." } };
|
|
363
|
+
}
|
|
262
364
|
window.location.assign(passkeyUrl(o));
|
|
365
|
+
return { ok: true, status: "redirected" };
|
|
263
366
|
},
|
|
264
367
|
socialUrl,
|
|
265
368
|
social(provider, o) {
|
|
@@ -303,7 +406,16 @@ function createAuthClient(options = {}) {
|
|
|
303
406
|
const body = await read("/me/sessions");
|
|
304
407
|
return body && Array.isArray(body.sessions) ? body.sessions : [];
|
|
305
408
|
},
|
|
306
|
-
signOutEverywhere: () => post("/me/sessions/end", {}, null)
|
|
409
|
+
signOutEverywhere: () => post("/me/sessions/end", {}, null),
|
|
410
|
+
async passkeys() {
|
|
411
|
+
const body = await read("/me/passkeys");
|
|
412
|
+
return body && Array.isArray(body.passkeys) ? body.passkeys : [];
|
|
413
|
+
},
|
|
414
|
+
addPasskey(f = {}) {
|
|
415
|
+
if (!canUsePasskeys()) return Promise.resolve({ ok: false, error: { code: "passkey_unavailable", message: "This browser cannot make passkeys." } });
|
|
416
|
+
return ceremony("/me/passkeys/add/begin", "/me/passkeys/add/finish", { password: f.password ?? "" }, makePasskey, { name: f.name ?? "" });
|
|
417
|
+
},
|
|
418
|
+
removePasskey: (id) => post("/me/passkeys/remove", { id }, null)
|
|
307
419
|
},
|
|
308
420
|
async getSession() {
|
|
309
421
|
try {
|
|
@@ -318,19 +430,13 @@ function createAuthClient(options = {}) {
|
|
|
318
430
|
looked ??= read("/look").then((wire) => wire && typeof wire === "object" ? fromWire(wire) : null);
|
|
319
431
|
return looked;
|
|
320
432
|
},
|
|
321
|
-
|
|
322
|
-
try {
|
|
323
|
-
const res = await doFetch(`${base}/methods`, { credentials: "same-origin", headers: { accept: "application/json" } });
|
|
324
|
-
if (res.ok) return await res.json();
|
|
325
|
-
} catch {
|
|
326
|
-
}
|
|
327
|
-
return { providers: [], signUp: true, magicLink: false, passkey: false };
|
|
328
|
-
}
|
|
433
|
+
methods
|
|
329
434
|
};
|
|
330
435
|
}
|
|
331
436
|
// Annotate the CommonJS export names for ESM import in node:
|
|
332
437
|
0 && (module.exports = {
|
|
333
438
|
MIN_PASSWORD,
|
|
439
|
+
canUsePasskeys,
|
|
334
440
|
checkCode,
|
|
335
441
|
checkEmail,
|
|
336
442
|
checkName,
|