cauthy-auth 0.10.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 +54 -5
- package/dist/client.d.ts +54 -5
- package/dist/client.js +113 -11
- package/dist/client.js.map +1 -1
- package/dist/client.mjs +112 -11
- package/dist/client.mjs.map +1 -1
- package/dist/index.js +115 -5
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +115 -5
- package/dist/index.mjs.map +1 -1
- package/dist/react.d.mts +61 -5
- package/dist/react.d.ts +61 -5
- package/dist/react.js +198 -17
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +197 -17
- 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 +111 -11
- package/dist/svelte.js.map +1 -1
- package/dist/svelte.mjs +111 -11
- 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 +111 -11
- package/dist/vue.js.map +1 -1
- package/dist/vue.mjs +111 -11
- package/dist/vue.mjs.map +1 -1
- package/package.json +1 -1
package/dist/vue.mjs
CHANGED
|
@@ -1,6 +1,73 @@
|
|
|
1
1
|
// src/vue.ts
|
|
2
2
|
import { inject, shallowReadonly, shallowRef } from "vue";
|
|
3
3
|
|
|
4
|
+
// src/passkey.ts
|
|
5
|
+
function canUsePasskeys() {
|
|
6
|
+
return typeof window !== "undefined" && typeof window.PublicKeyCredential === "function" && typeof navigator !== "undefined" && typeof navigator.credentials?.get === "function";
|
|
7
|
+
}
|
|
8
|
+
function bytes(text2) {
|
|
9
|
+
const b64 = text2.replace(/-/g, "+").replace(/_/g, "/").padEnd(Math.ceil(text2.length / 4) * 4, "=");
|
|
10
|
+
const bin = atob(b64);
|
|
11
|
+
const out = new Uint8Array(bin.length);
|
|
12
|
+
for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
|
|
13
|
+
return out.buffer;
|
|
14
|
+
}
|
|
15
|
+
function text(buf) {
|
|
16
|
+
if (!buf) return null;
|
|
17
|
+
const view = new Uint8Array(buf);
|
|
18
|
+
let bin = "";
|
|
19
|
+
for (let i = 0; i < view.byteLength; i++) bin += String.fromCharCode(view[i]);
|
|
20
|
+
return btoa(bin).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
21
|
+
}
|
|
22
|
+
var withId = (list) => (list ?? []).map((c) => ({ ...c, id: bytes(c.id) }));
|
|
23
|
+
async function getPasskey(options) {
|
|
24
|
+
const publicKey = { ...options, challenge: bytes(options.challenge), allowCredentials: withId(options.allowCredentials) };
|
|
25
|
+
const cred = await navigator.credentials.get({ publicKey });
|
|
26
|
+
if (cred === null) throw new DOMException("No passkey was chosen.", "NotAllowedError");
|
|
27
|
+
const r = cred.response;
|
|
28
|
+
return {
|
|
29
|
+
id: cred.id,
|
|
30
|
+
rawId: text(cred.rawId),
|
|
31
|
+
type: cred.type,
|
|
32
|
+
response: {
|
|
33
|
+
authenticatorData: text(r.authenticatorData),
|
|
34
|
+
clientDataJSON: text(r.clientDataJSON),
|
|
35
|
+
signature: text(r.signature),
|
|
36
|
+
userHandle: text(r.userHandle)
|
|
37
|
+
},
|
|
38
|
+
clientExtensionResults: cred.getClientExtensionResults?.() ?? {}
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
async function makePasskey(options) {
|
|
42
|
+
const publicKey = {
|
|
43
|
+
...options,
|
|
44
|
+
challenge: bytes(options.challenge),
|
|
45
|
+
user: { ...options.user, id: bytes(options.user.id) },
|
|
46
|
+
excludeCredentials: withId(options.excludeCredentials)
|
|
47
|
+
};
|
|
48
|
+
const cred = await navigator.credentials.create({ publicKey });
|
|
49
|
+
if (cred === null) throw new DOMException("No passkey was made.", "NotAllowedError");
|
|
50
|
+
const r = cred.response;
|
|
51
|
+
return {
|
|
52
|
+
id: cred.id,
|
|
53
|
+
rawId: text(cred.rawId),
|
|
54
|
+
type: cred.type,
|
|
55
|
+
response: {
|
|
56
|
+
clientDataJSON: text(r.clientDataJSON),
|
|
57
|
+
attestationObject: text(r.attestationObject),
|
|
58
|
+
transports: typeof r.getTransports === "function" ? r.getTransports() : []
|
|
59
|
+
},
|
|
60
|
+
clientExtensionResults: cred.getClientExtensionResults?.() ?? {}
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function ceremonyError(e) {
|
|
64
|
+
const name = e instanceof Error || e instanceof DOMException ? e.name : "";
|
|
65
|
+
if (name === "NotAllowedError" || name === "AbortError") return { code: "cancelled", message: "The passkey was not used. Try again when you are ready." };
|
|
66
|
+
if (name === "InvalidStateError") return { code: "passkey_exists", message: "This device already has a passkey for this account." };
|
|
67
|
+
if (name === "SecurityError") return { code: "passkey_unavailable", message: "Passkeys cannot be used on this page." };
|
|
68
|
+
return { code: "passkey_failed", message: "The passkey could not be used. Try again, or sign in another way." };
|
|
69
|
+
}
|
|
70
|
+
|
|
4
71
|
// src/theme.ts
|
|
5
72
|
function fromWire(wire) {
|
|
6
73
|
const names = {
|
|
@@ -117,6 +184,28 @@ function createAuthClient(options = {}) {
|
|
|
117
184
|
if (o.locale) q.set("locale", o.locale);
|
|
118
185
|
return `${base}/login?${q}`;
|
|
119
186
|
};
|
|
187
|
+
async function methods() {
|
|
188
|
+
try {
|
|
189
|
+
const res = await doFetch(`${base}/methods`, { credentials: "same-origin", headers: { accept: "application/json" } });
|
|
190
|
+
if (res.ok) {
|
|
191
|
+
const m = await res.json();
|
|
192
|
+
return { providers: [], signUp: true, magicLink: false, passkey: false, ...m, passkeyHere: m.passkeyHere === true, passkeyOnCauthy: m.passkeyOnCauthy ?? m.passkey === true };
|
|
193
|
+
}
|
|
194
|
+
} catch {
|
|
195
|
+
}
|
|
196
|
+
return { providers: [], signUp: true, magicLink: false, passkey: false, passkeyHere: false, passkeyOnCauthy: false };
|
|
197
|
+
}
|
|
198
|
+
async function ceremony(begin, finish, form, run, more = {}) {
|
|
199
|
+
const begun = await post(begin, form, null);
|
|
200
|
+
if (!begun.ok) return begun;
|
|
201
|
+
let credential;
|
|
202
|
+
try {
|
|
203
|
+
credential = await run(begun.options);
|
|
204
|
+
} catch (e) {
|
|
205
|
+
return { ok: false, error: ceremonyError(e) };
|
|
206
|
+
}
|
|
207
|
+
return post(finish, { credential, ...more }, null);
|
|
208
|
+
}
|
|
120
209
|
return {
|
|
121
210
|
signIn: {
|
|
122
211
|
email: (f) => post("/sign-in/email", { email: f.email, password: f.password }, firstProblem(checkEmail(f.email), checkPassword(f.password))),
|
|
@@ -125,8 +214,16 @@ function createAuthClient(options = {}) {
|
|
|
125
214
|
magicLinkVerify: (f) => post("/sign-in/magic-link/verify", { token: f.token }, null),
|
|
126
215
|
emailCode: (f) => post("/sign-in/email-code", { code: f.code }, checkCode(f.code)),
|
|
127
216
|
passkeyUrl,
|
|
128
|
-
passkey(o) {
|
|
217
|
+
async passkey(o) {
|
|
218
|
+
const m = await methods();
|
|
219
|
+
if (m.passkeyHere && canUsePasskeys()) {
|
|
220
|
+
const r = await ceremony("/sign-in/passkey/begin", "/sign-in/passkey/finish", {}, getPasskey);
|
|
221
|
+
if (r.ok || r.error.code !== "passkey_unavailable" || !m.passkeyOnCauthy) return r;
|
|
222
|
+
} else if (!m.passkeyOnCauthy) {
|
|
223
|
+
return { ok: false, error: { code: "passkey_unavailable", message: "Passkeys cannot be used here." } };
|
|
224
|
+
}
|
|
129
225
|
window.location.assign(passkeyUrl(o));
|
|
226
|
+
return { ok: true, status: "redirected" };
|
|
130
227
|
},
|
|
131
228
|
socialUrl,
|
|
132
229
|
social(provider, o) {
|
|
@@ -170,7 +267,16 @@ function createAuthClient(options = {}) {
|
|
|
170
267
|
const body = await read("/me/sessions");
|
|
171
268
|
return body && Array.isArray(body.sessions) ? body.sessions : [];
|
|
172
269
|
},
|
|
173
|
-
signOutEverywhere: () => post("/me/sessions/end", {}, null)
|
|
270
|
+
signOutEverywhere: () => post("/me/sessions/end", {}, null),
|
|
271
|
+
async passkeys() {
|
|
272
|
+
const body = await read("/me/passkeys");
|
|
273
|
+
return body && Array.isArray(body.passkeys) ? body.passkeys : [];
|
|
274
|
+
},
|
|
275
|
+
addPasskey(f = {}) {
|
|
276
|
+
if (!canUsePasskeys()) return Promise.resolve({ ok: false, error: { code: "passkey_unavailable", message: "This browser cannot make passkeys." } });
|
|
277
|
+
return ceremony("/me/passkeys/add/begin", "/me/passkeys/add/finish", { password: f.password ?? "" }, makePasskey, { name: f.name ?? "" });
|
|
278
|
+
},
|
|
279
|
+
removePasskey: (id) => post("/me/passkeys/remove", { id }, null)
|
|
174
280
|
},
|
|
175
281
|
async getSession() {
|
|
176
282
|
try {
|
|
@@ -185,14 +291,7 @@ function createAuthClient(options = {}) {
|
|
|
185
291
|
looked ??= read("/look").then((wire) => wire && typeof wire === "object" ? fromWire(wire) : null);
|
|
186
292
|
return looked;
|
|
187
293
|
},
|
|
188
|
-
|
|
189
|
-
try {
|
|
190
|
-
const res = await doFetch(`${base}/methods`, { credentials: "same-origin", headers: { accept: "application/json" } });
|
|
191
|
-
if (res.ok) return await res.json();
|
|
192
|
-
} catch {
|
|
193
|
-
}
|
|
194
|
-
return { providers: [], signUp: true, magicLink: false, passkey: false };
|
|
195
|
-
}
|
|
294
|
+
methods
|
|
196
295
|
};
|
|
197
296
|
}
|
|
198
297
|
|
|
@@ -288,7 +387,8 @@ function createSessionStore(options = {}) {
|
|
|
288
387
|
email: (f) => then(client.signIn.email(f)),
|
|
289
388
|
mfa: (f) => then(client.signIn.mfa(f)),
|
|
290
389
|
magicLinkVerify: (f) => then(client.signIn.magicLinkVerify(f)),
|
|
291
|
-
emailCode: (f) => then(client.signIn.emailCode(f))
|
|
390
|
+
emailCode: (f) => then(client.signIn.emailCode(f)),
|
|
391
|
+
passkey: (o) => then(client.signIn.passkey(o))
|
|
292
392
|
},
|
|
293
393
|
signUp: { email: (f) => then(client.signUp.email(f)) },
|
|
294
394
|
signOut: () => then(client.signOut()),
|