@camstack/addon-auth 1.1.4 → 1.1.6
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/{dist-JUeAGU3c.mjs → dist-BlBNW5nA.mjs} +69 -1
- package/dist/{dist-BLBS0d1z.js → dist-CS-GzG-v.js} +80 -0
- package/dist/magic-link/auth-magic-link.addon.js +1 -1
- package/dist/magic-link/auth-magic-link.addon.mjs +1 -1
- package/dist/oidc/auth-oidc.addon.js +1 -1
- package/dist/oidc/auth-oidc.addon.mjs +1 -1
- package/dist/webauthn/_stub.js +121 -9
- package/dist/webauthn/{_virtual_mf-localSharedImportMap___mfe_internal__addon_auth_webauthn_widgets-Bg_T1-iY.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_auth_webauthn_widgets-Du23U8IZ.mjs} +2 -2
- package/dist/webauthn/auth-webauthn.addon.js +281 -55
- package/dist/webauthn/auth-webauthn.addon.mjs +281 -55
- package/dist/webauthn/{hostInit-Boe91Eeg.mjs → hostInit-Cq4HnxlU.mjs} +2 -2
- package/dist/webauthn/remoteEntry.js +1 -1
- package/package.json +1 -1
|
@@ -16401,10 +16401,32 @@ method(_void(), array(TurnServerSchema).readonly());
|
|
|
16401
16401
|
* b. `finishAuthentication({userId, response})` → server verifies
|
|
16402
16402
|
* the assertion, bumps the credential counter, returns ok.
|
|
16403
16403
|
*
|
|
16404
|
+
* 2b. Usernameless (discoverable-credential) authentication — the
|
|
16405
|
+
* passkey IS the primary factor, no password leg:
|
|
16406
|
+
* a. `beginDiscoverableAuthentication({})` → assertion options with
|
|
16407
|
+
* EMPTY `allowCredentials` (the browser offers every resident
|
|
16408
|
+
* passkey it holds for this RP) + `userVerification: 'required'`
|
|
16409
|
+
* (the passkey replaces both factors, so UV is mandatory).
|
|
16410
|
+
* The challenge is stored server-side, NOT bound to any user.
|
|
16411
|
+
* b. `finishDiscoverableAuthentication({response})` → the provider
|
|
16412
|
+
* resolves the credential by the response's credential id,
|
|
16413
|
+
* verifies the assertion against the stored challenge + that
|
|
16414
|
+
* credential's public key/counter, and returns the OWNING
|
|
16415
|
+
* `userId` — the caller (core auth router) mints the session.
|
|
16416
|
+
*
|
|
16404
16417
|
* 3. Management:
|
|
16405
16418
|
* - `listPasskeys({userId})` — enumerate user's enrolled credentials.
|
|
16406
16419
|
* - `removePasskey({userId, credentialId})` — revoke one credential.
|
|
16407
16420
|
*
|
|
16421
|
+
* 4. Second-factor preference (opt-in, default OFF):
|
|
16422
|
+
* Enrolling a passkey only enables passkey-FIRST sign-in. It is
|
|
16423
|
+
* demanded as a second factor after a password login ONLY when the
|
|
16424
|
+
* user explicitly opts in via `setSecondFactorPreference`.
|
|
16425
|
+
* - `getSecondFactorPreference({userId})` → `{ enabled }` (missing
|
|
16426
|
+
* row ⇒ `enabled: false`).
|
|
16427
|
+
* - `setSecondFactorPreference({userId, enabled})` — persisted by
|
|
16428
|
+
* the providing addon beside its credentials.
|
|
16429
|
+
*
|
|
16408
16430
|
* Challenges are short-lived (5 min, in-memory). The cap is internal —
|
|
16409
16431
|
* the admin-ui composes the begin/finish round-trip and never exposes
|
|
16410
16432
|
* the cap to non-admins.
|
|
@@ -16457,6 +16479,19 @@ var userPasskeysCapability = {
|
|
|
16457
16479
|
kind: "mutation",
|
|
16458
16480
|
access: "view"
|
|
16459
16481
|
}),
|
|
16482
|
+
beginDiscoverableAuthentication: method(object({}), object({ optionsJSON: record(string(), unknown()) }), {
|
|
16483
|
+
kind: "mutation",
|
|
16484
|
+
access: "view"
|
|
16485
|
+
}),
|
|
16486
|
+
finishDiscoverableAuthentication: method(object({
|
|
16487
|
+
/** AuthenticationResponseJSON from the browser. */
|
|
16488
|
+
response: record(string(), unknown()) }), object({
|
|
16489
|
+
verified: boolean(),
|
|
16490
|
+
userId: string().nullable()
|
|
16491
|
+
}), {
|
|
16492
|
+
kind: "mutation",
|
|
16493
|
+
access: "view"
|
|
16494
|
+
}),
|
|
16460
16495
|
listPasskeys: method(object({ userId: string() }), array(PasskeySummarySchema), { auth: "admin" }),
|
|
16461
16496
|
removePasskey: method(object({
|
|
16462
16497
|
userId: string(),
|
|
@@ -16465,6 +16500,15 @@ var userPasskeysCapability = {
|
|
|
16465
16500
|
kind: "mutation",
|
|
16466
16501
|
auth: "admin",
|
|
16467
16502
|
access: "delete"
|
|
16503
|
+
}),
|
|
16504
|
+
getSecondFactorPreference: method(object({ userId: string() }), object({ enabled: boolean() }), { auth: "admin" }),
|
|
16505
|
+
setSecondFactorPreference: method(object({
|
|
16506
|
+
userId: string(),
|
|
16507
|
+
enabled: boolean()
|
|
16508
|
+
}), object({ success: literal(true) }), {
|
|
16509
|
+
kind: "mutation",
|
|
16510
|
+
auth: "admin",
|
|
16511
|
+
access: "create"
|
|
16468
16512
|
})
|
|
16469
16513
|
}
|
|
16470
16514
|
};
|
|
@@ -22959,6 +23003,12 @@ Object.freeze({
|
|
|
22959
23003
|
addonId: null,
|
|
22960
23004
|
access: "view"
|
|
22961
23005
|
},
|
|
23006
|
+
"userPasskeys.beginDiscoverableAuthentication": {
|
|
23007
|
+
capName: "user-passkeys",
|
|
23008
|
+
capScope: "system",
|
|
23009
|
+
addonId: null,
|
|
23010
|
+
access: "view"
|
|
23011
|
+
},
|
|
22962
23012
|
"userPasskeys.beginRegistration": {
|
|
22963
23013
|
capName: "user-passkeys",
|
|
22964
23014
|
capScope: "system",
|
|
@@ -22971,12 +23021,24 @@ Object.freeze({
|
|
|
22971
23021
|
addonId: null,
|
|
22972
23022
|
access: "view"
|
|
22973
23023
|
},
|
|
23024
|
+
"userPasskeys.finishDiscoverableAuthentication": {
|
|
23025
|
+
capName: "user-passkeys",
|
|
23026
|
+
capScope: "system",
|
|
23027
|
+
addonId: null,
|
|
23028
|
+
access: "view"
|
|
23029
|
+
},
|
|
22974
23030
|
"userPasskeys.finishRegistration": {
|
|
22975
23031
|
capName: "user-passkeys",
|
|
22976
23032
|
capScope: "system",
|
|
22977
23033
|
addonId: null,
|
|
22978
23034
|
access: "create"
|
|
22979
23035
|
},
|
|
23036
|
+
"userPasskeys.getSecondFactorPreference": {
|
|
23037
|
+
capName: "user-passkeys",
|
|
23038
|
+
capScope: "system",
|
|
23039
|
+
addonId: null,
|
|
23040
|
+
access: "view"
|
|
23041
|
+
},
|
|
22980
23042
|
"userPasskeys.listPasskeys": {
|
|
22981
23043
|
capName: "user-passkeys",
|
|
22982
23044
|
capScope: "system",
|
|
@@ -22989,6 +23051,12 @@ Object.freeze({
|
|
|
22989
23051
|
addonId: null,
|
|
22990
23052
|
access: "delete"
|
|
22991
23053
|
},
|
|
23054
|
+
"userPasskeys.setSecondFactorPreference": {
|
|
23055
|
+
capName: "user-passkeys",
|
|
23056
|
+
capScope: "system",
|
|
23057
|
+
addonId: null,
|
|
23058
|
+
access: "create"
|
|
23059
|
+
},
|
|
22992
23060
|
"vacuumControl.locate": {
|
|
22993
23061
|
capName: "vacuum-control",
|
|
22994
23062
|
capScope: "device",
|
|
@@ -23241,4 +23309,4 @@ object({
|
|
|
23241
23309
|
schemaVersion: literal(1)
|
|
23242
23310
|
});
|
|
23243
23311
|
//#endregion
|
|
23244
|
-
export { loginMethodCapability as a, BaseAddon as c,
|
|
23312
|
+
export { loginMethodCapability as a, BaseAddon as c, number as d, object as f, buildAddonRouteProvider as i, array as l, addonWidgetsSourceCapability as n, userPasskeysCapability as o, string as p, authProviderCapability as r, errMsg as s, addonRoutesCapability as t, boolean as u };
|
|
@@ -16401,10 +16401,32 @@ method(_void(), array(TurnServerSchema).readonly());
|
|
|
16401
16401
|
* b. `finishAuthentication({userId, response})` → server verifies
|
|
16402
16402
|
* the assertion, bumps the credential counter, returns ok.
|
|
16403
16403
|
*
|
|
16404
|
+
* 2b. Usernameless (discoverable-credential) authentication — the
|
|
16405
|
+
* passkey IS the primary factor, no password leg:
|
|
16406
|
+
* a. `beginDiscoverableAuthentication({})` → assertion options with
|
|
16407
|
+
* EMPTY `allowCredentials` (the browser offers every resident
|
|
16408
|
+
* passkey it holds for this RP) + `userVerification: 'required'`
|
|
16409
|
+
* (the passkey replaces both factors, so UV is mandatory).
|
|
16410
|
+
* The challenge is stored server-side, NOT bound to any user.
|
|
16411
|
+
* b. `finishDiscoverableAuthentication({response})` → the provider
|
|
16412
|
+
* resolves the credential by the response's credential id,
|
|
16413
|
+
* verifies the assertion against the stored challenge + that
|
|
16414
|
+
* credential's public key/counter, and returns the OWNING
|
|
16415
|
+
* `userId` — the caller (core auth router) mints the session.
|
|
16416
|
+
*
|
|
16404
16417
|
* 3. Management:
|
|
16405
16418
|
* - `listPasskeys({userId})` — enumerate user's enrolled credentials.
|
|
16406
16419
|
* - `removePasskey({userId, credentialId})` — revoke one credential.
|
|
16407
16420
|
*
|
|
16421
|
+
* 4. Second-factor preference (opt-in, default OFF):
|
|
16422
|
+
* Enrolling a passkey only enables passkey-FIRST sign-in. It is
|
|
16423
|
+
* demanded as a second factor after a password login ONLY when the
|
|
16424
|
+
* user explicitly opts in via `setSecondFactorPreference`.
|
|
16425
|
+
* - `getSecondFactorPreference({userId})` → `{ enabled }` (missing
|
|
16426
|
+
* row ⇒ `enabled: false`).
|
|
16427
|
+
* - `setSecondFactorPreference({userId, enabled})` — persisted by
|
|
16428
|
+
* the providing addon beside its credentials.
|
|
16429
|
+
*
|
|
16408
16430
|
* Challenges are short-lived (5 min, in-memory). The cap is internal —
|
|
16409
16431
|
* the admin-ui composes the begin/finish round-trip and never exposes
|
|
16410
16432
|
* the cap to non-admins.
|
|
@@ -16457,6 +16479,19 @@ var userPasskeysCapability = {
|
|
|
16457
16479
|
kind: "mutation",
|
|
16458
16480
|
access: "view"
|
|
16459
16481
|
}),
|
|
16482
|
+
beginDiscoverableAuthentication: method(object({}), object({ optionsJSON: record(string(), unknown()) }), {
|
|
16483
|
+
kind: "mutation",
|
|
16484
|
+
access: "view"
|
|
16485
|
+
}),
|
|
16486
|
+
finishDiscoverableAuthentication: method(object({
|
|
16487
|
+
/** AuthenticationResponseJSON from the browser. */
|
|
16488
|
+
response: record(string(), unknown()) }), object({
|
|
16489
|
+
verified: boolean(),
|
|
16490
|
+
userId: string().nullable()
|
|
16491
|
+
}), {
|
|
16492
|
+
kind: "mutation",
|
|
16493
|
+
access: "view"
|
|
16494
|
+
}),
|
|
16460
16495
|
listPasskeys: method(object({ userId: string() }), array(PasskeySummarySchema), { auth: "admin" }),
|
|
16461
16496
|
removePasskey: method(object({
|
|
16462
16497
|
userId: string(),
|
|
@@ -16465,6 +16500,15 @@ var userPasskeysCapability = {
|
|
|
16465
16500
|
kind: "mutation",
|
|
16466
16501
|
auth: "admin",
|
|
16467
16502
|
access: "delete"
|
|
16503
|
+
}),
|
|
16504
|
+
getSecondFactorPreference: method(object({ userId: string() }), object({ enabled: boolean() }), { auth: "admin" }),
|
|
16505
|
+
setSecondFactorPreference: method(object({
|
|
16506
|
+
userId: string(),
|
|
16507
|
+
enabled: boolean()
|
|
16508
|
+
}), object({ success: literal(true) }), {
|
|
16509
|
+
kind: "mutation",
|
|
16510
|
+
auth: "admin",
|
|
16511
|
+
access: "create"
|
|
16468
16512
|
})
|
|
16469
16513
|
}
|
|
16470
16514
|
};
|
|
@@ -22959,6 +23003,12 @@ Object.freeze({
|
|
|
22959
23003
|
addonId: null,
|
|
22960
23004
|
access: "view"
|
|
22961
23005
|
},
|
|
23006
|
+
"userPasskeys.beginDiscoverableAuthentication": {
|
|
23007
|
+
capName: "user-passkeys",
|
|
23008
|
+
capScope: "system",
|
|
23009
|
+
addonId: null,
|
|
23010
|
+
access: "view"
|
|
23011
|
+
},
|
|
22962
23012
|
"userPasskeys.beginRegistration": {
|
|
22963
23013
|
capName: "user-passkeys",
|
|
22964
23014
|
capScope: "system",
|
|
@@ -22971,12 +23021,24 @@ Object.freeze({
|
|
|
22971
23021
|
addonId: null,
|
|
22972
23022
|
access: "view"
|
|
22973
23023
|
},
|
|
23024
|
+
"userPasskeys.finishDiscoverableAuthentication": {
|
|
23025
|
+
capName: "user-passkeys",
|
|
23026
|
+
capScope: "system",
|
|
23027
|
+
addonId: null,
|
|
23028
|
+
access: "view"
|
|
23029
|
+
},
|
|
22974
23030
|
"userPasskeys.finishRegistration": {
|
|
22975
23031
|
capName: "user-passkeys",
|
|
22976
23032
|
capScope: "system",
|
|
22977
23033
|
addonId: null,
|
|
22978
23034
|
access: "create"
|
|
22979
23035
|
},
|
|
23036
|
+
"userPasskeys.getSecondFactorPreference": {
|
|
23037
|
+
capName: "user-passkeys",
|
|
23038
|
+
capScope: "system",
|
|
23039
|
+
addonId: null,
|
|
23040
|
+
access: "view"
|
|
23041
|
+
},
|
|
22980
23042
|
"userPasskeys.listPasskeys": {
|
|
22981
23043
|
capName: "user-passkeys",
|
|
22982
23044
|
capScope: "system",
|
|
@@ -22989,6 +23051,12 @@ Object.freeze({
|
|
|
22989
23051
|
addonId: null,
|
|
22990
23052
|
access: "delete"
|
|
22991
23053
|
},
|
|
23054
|
+
"userPasskeys.setSecondFactorPreference": {
|
|
23055
|
+
capName: "user-passkeys",
|
|
23056
|
+
capScope: "system",
|
|
23057
|
+
addonId: null,
|
|
23058
|
+
access: "create"
|
|
23059
|
+
},
|
|
22992
23060
|
"vacuumControl.locate": {
|
|
22993
23061
|
capName: "vacuum-control",
|
|
22994
23062
|
capScope: "device",
|
|
@@ -23271,6 +23339,12 @@ Object.defineProperty(exports, "authProviderCapability", {
|
|
|
23271
23339
|
return authProviderCapability;
|
|
23272
23340
|
}
|
|
23273
23341
|
});
|
|
23342
|
+
Object.defineProperty(exports, "boolean", {
|
|
23343
|
+
enumerable: true,
|
|
23344
|
+
get: function() {
|
|
23345
|
+
return boolean;
|
|
23346
|
+
}
|
|
23347
|
+
});
|
|
23274
23348
|
Object.defineProperty(exports, "buildAddonRouteProvider", {
|
|
23275
23349
|
enumerable: true,
|
|
23276
23350
|
get: function() {
|
|
@@ -23289,6 +23363,12 @@ Object.defineProperty(exports, "loginMethodCapability", {
|
|
|
23289
23363
|
return loginMethodCapability;
|
|
23290
23364
|
}
|
|
23291
23365
|
});
|
|
23366
|
+
Object.defineProperty(exports, "number", {
|
|
23367
|
+
enumerable: true,
|
|
23368
|
+
get: function() {
|
|
23369
|
+
return number;
|
|
23370
|
+
}
|
|
23371
|
+
});
|
|
23292
23372
|
Object.defineProperty(exports, "object", {
|
|
23293
23373
|
enumerable: true,
|
|
23294
23374
|
get: function() {
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
require("../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../dist-
|
|
6
|
+
const require_dist = require("../dist-CS-GzG-v.js");
|
|
7
7
|
//#region src/magic-link/auth-magic-link.addon.ts
|
|
8
8
|
/**
|
|
9
9
|
* Magic-link authentication addon.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as loginMethodCapability, c as BaseAddon, i as buildAddonRouteProvider, r as authProviderCapability, s as errMsg, t as addonRoutesCapability } from "../dist-
|
|
1
|
+
import { a as loginMethodCapability, c as BaseAddon, i as buildAddonRouteProvider, r as authProviderCapability, s as errMsg, t as addonRoutesCapability } from "../dist-BlBNW5nA.mjs";
|
|
2
2
|
//#region src/magic-link/auth-magic-link.addon.ts
|
|
3
3
|
/**
|
|
4
4
|
* Magic-link authentication addon.
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../dist-
|
|
6
|
+
const require_dist = require("../dist-CS-GzG-v.js");
|
|
7
7
|
let node_crypto = require("node:crypto");
|
|
8
8
|
node_crypto = require_chunk.__toESM(node_crypto);
|
|
9
9
|
//#region node_modules/jose/dist/webapi/lib/buffer_utils.js
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as loginMethodCapability, c as BaseAddon, i as buildAddonRouteProvider, r as authProviderCapability, s as errMsg, t as addonRoutesCapability } from "../dist-
|
|
1
|
+
import { a as loginMethodCapability, c as BaseAddon, i as buildAddonRouteProvider, r as authProviderCapability, s as errMsg, t as addonRoutesCapability } from "../dist-BlBNW5nA.mjs";
|
|
2
2
|
import * as crypto$1 from "node:crypto";
|
|
3
3
|
//#region node_modules/jose/dist/webapi/lib/buffer_utils.js
|
|
4
4
|
var encoder = new TextEncoder();
|
package/dist/webauthn/_stub.js
CHANGED
|
@@ -414,7 +414,17 @@ function B(e) {
|
|
|
414
414
|
let n = a(), l = r({
|
|
415
415
|
queryKey: ["auth", "listOwnPasskeys"],
|
|
416
416
|
queryFn: () => n.listOwnPasskeys()
|
|
417
|
-
}), u = l.data ?? [], [d, f] = t(""), [p, m] = t(!1), [h, g] = t(null), S =
|
|
417
|
+
}), u = l.data ?? [], [d, f] = t(""), [p, m] = t(!1), [h, g] = t(null), S = r({
|
|
418
|
+
queryKey: ["auth", "getOwnPasskeySecondFactorPreference"],
|
|
419
|
+
queryFn: () => n.getOwnPasskeySecondFactorPreference(),
|
|
420
|
+
enabled: u.length > 0
|
|
421
|
+
}), C = S.data?.enabled ?? !1, w = i({
|
|
422
|
+
mutationFn: (e) => n.setOwnPasskeySecondFactorPreference({ enabled: e }),
|
|
423
|
+
onSuccess: () => {
|
|
424
|
+
g(null), S.refetch();
|
|
425
|
+
},
|
|
426
|
+
onError: (e) => g(e instanceof Error ? e.message : "Could not update the preference")
|
|
427
|
+
}), T = async () => {
|
|
418
428
|
g(null), m(!0);
|
|
419
429
|
try {
|
|
420
430
|
let e = await z((await n.beginOwnPasskeyRegistration()).optionsJSON);
|
|
@@ -427,7 +437,7 @@ function B(e) {
|
|
|
427
437
|
} finally {
|
|
428
438
|
m(!1);
|
|
429
439
|
}
|
|
430
|
-
},
|
|
440
|
+
}, E = i({
|
|
431
441
|
mutationFn: (e) => n.removeOwnPasskey({ credentialId: e }),
|
|
432
442
|
onSuccess: () => {
|
|
433
443
|
g(null), l.refetch();
|
|
@@ -447,7 +457,7 @@ function B(e) {
|
|
|
447
457
|
children: [
|
|
448
458
|
/* @__PURE__ */ o("div", {
|
|
449
459
|
className: "text-xs text-foreground-subtle",
|
|
450
|
-
children: "Add a passkey (Touch ID, Windows Hello, or a security key)
|
|
460
|
+
children: "Add a passkey (Touch ID, Windows Hello, or a security key) to sign in directly — fast and phishing-resistant, no password needed."
|
|
451
461
|
}),
|
|
452
462
|
l.isLoading ? /* @__PURE__ */ s("div", {
|
|
453
463
|
className: "flex items-center gap-2 text-xs text-foreground-subtle",
|
|
@@ -473,8 +483,8 @@ function B(e) {
|
|
|
473
483
|
})]
|
|
474
484
|
}),
|
|
475
485
|
/* @__PURE__ */ s("button", {
|
|
476
|
-
onClick: () =>
|
|
477
|
-
disabled:
|
|
486
|
+
onClick: () => E.mutate(e.credentialId),
|
|
487
|
+
disabled: E.isPending,
|
|
478
488
|
className: "inline-flex items-center gap-1 rounded px-2 py-1 text-[11px] text-danger hover:bg-danger/10 disabled:opacity-50",
|
|
479
489
|
children: [/* @__PURE__ */ o(x, { className: "h-3 w-3" }), "Remove"]
|
|
480
490
|
})
|
|
@@ -484,6 +494,28 @@ function B(e) {
|
|
|
484
494
|
className: "text-[11px] text-foreground-subtle",
|
|
485
495
|
children: "No passkeys enrolled yet."
|
|
486
496
|
}),
|
|
497
|
+
u.length > 0 && /* @__PURE__ */ s("div", {
|
|
498
|
+
className: "flex items-start justify-between gap-3 rounded-md border border-border px-3 py-2.5",
|
|
499
|
+
children: [/* @__PURE__ */ s("div", {
|
|
500
|
+
className: "min-w-0",
|
|
501
|
+
children: [/* @__PURE__ */ o("div", {
|
|
502
|
+
className: "text-xs font-medium text-foreground",
|
|
503
|
+
children: "Require passkey as second factor"
|
|
504
|
+
}), /* @__PURE__ */ o("div", {
|
|
505
|
+
className: "text-[10px] text-foreground-subtle mt-0.5",
|
|
506
|
+
children: "Also ask for a passkey after every password sign-in. Off by default — enrolling a passkey on its own only enables direct passkey sign-in."
|
|
507
|
+
})]
|
|
508
|
+
}), /* @__PURE__ */ o("button", {
|
|
509
|
+
type: "button",
|
|
510
|
+
role: "switch",
|
|
511
|
+
"aria-checked": C,
|
|
512
|
+
"aria-label": "Require passkey as second factor",
|
|
513
|
+
onClick: () => w.mutate(!C),
|
|
514
|
+
disabled: S.isLoading || w.isPending,
|
|
515
|
+
className: `relative inline-flex h-5 w-9 shrink-0 items-center rounded-full transition-colors disabled:opacity-50 ${C ? "bg-primary" : "bg-foreground-subtle/30"}`,
|
|
516
|
+
children: /* @__PURE__ */ o("span", { className: `inline-block h-3.5 w-3.5 rounded-full bg-white shadow transition-transform ${C ? "translate-x-[18px]" : "translate-x-[3px]"}` })
|
|
517
|
+
})]
|
|
518
|
+
}),
|
|
487
519
|
h && /* @__PURE__ */ s("div", {
|
|
488
520
|
className: "text-[11px] text-danger flex items-center gap-1",
|
|
489
521
|
children: [/* @__PURE__ */ o(_, { className: "h-3 w-3" }), h]
|
|
@@ -503,7 +535,7 @@ function B(e) {
|
|
|
503
535
|
className: "w-full rounded border border-border bg-background px-2 py-1.5 text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-primary"
|
|
504
536
|
})]
|
|
505
537
|
}), /* @__PURE__ */ o("button", {
|
|
506
|
-
onClick:
|
|
538
|
+
onClick: T,
|
|
507
539
|
disabled: p,
|
|
508
540
|
className: "inline-flex items-center gap-1.5 rounded-lg bg-primary px-3 py-2 text-xs font-semibold text-primary-foreground hover:opacity-90 disabled:opacity-50",
|
|
509
541
|
children: p ? /* @__PURE__ */ s(c, { children: [/* @__PURE__ */ o(b, { className: "h-3.5 w-3.5 animate-spin" }), "Enrolling…"] }) : /* @__PURE__ */ s(c, { children: [/* @__PURE__ */ o(v, { className: "h-3.5 w-3.5" }), "Add passkey"] })
|
|
@@ -559,10 +591,90 @@ function H(e) {
|
|
|
559
591
|
});
|
|
560
592
|
}
|
|
561
593
|
//#endregion
|
|
562
|
-
//#region src/webauthn/widgets/
|
|
594
|
+
//#region src/webauthn/widgets/direct-login-i18n.ts
|
|
563
595
|
var U = {
|
|
596
|
+
en: {
|
|
597
|
+
signInWithPasskey: "Sign in with a passkey",
|
|
598
|
+
unsupported: "This browser does not support passkeys.",
|
|
599
|
+
failed: "Passkey sign-in failed",
|
|
600
|
+
secondFactorRequired: "Additional verification is required — sign in with your password to continue."
|
|
601
|
+
},
|
|
602
|
+
it: {
|
|
603
|
+
signInWithPasskey: "Accedi con una passkey",
|
|
604
|
+
unsupported: "Questo browser non supporta le passkey.",
|
|
605
|
+
failed: "Accesso con passkey non riuscito",
|
|
606
|
+
secondFactorRequired: "È richiesta una verifica aggiuntiva — accedi con la password per continuare."
|
|
607
|
+
}
|
|
608
|
+
};
|
|
609
|
+
function W(e) {
|
|
610
|
+
return (e ?? globalThis.navigator?.language ?? "en").toLowerCase().split("-")[0] === "it" ? "it" : "en";
|
|
611
|
+
}
|
|
612
|
+
function G(e, t) {
|
|
613
|
+
return U[e][t];
|
|
614
|
+
}
|
|
615
|
+
//#endregion
|
|
616
|
+
//#region src/webauthn/widgets/PasskeyDirectLogin.tsx
|
|
617
|
+
function K(e) {
|
|
618
|
+
if (!e) return null;
|
|
619
|
+
let t = e.onComplete, n = e.onSecondFactor, r = e.onError, i = e.locale;
|
|
620
|
+
return typeof t == "function" ? {
|
|
621
|
+
onComplete: t,
|
|
622
|
+
onSecondFactor: typeof n == "function" ? n : void 0,
|
|
623
|
+
onError: typeof r == "function" ? r : void 0,
|
|
624
|
+
locale: typeof i == "string" ? i : void 0
|
|
625
|
+
} : null;
|
|
626
|
+
}
|
|
627
|
+
function q(e) {
|
|
628
|
+
let n = a(), r = K(e.config), [i, c] = t(!1), [l, u] = t(null), d = W(r?.locale);
|
|
629
|
+
return r ? L() ? /* @__PURE__ */ s("div", {
|
|
630
|
+
className: "space-y-2",
|
|
631
|
+
children: [/* @__PURE__ */ s("button", {
|
|
632
|
+
type: "button",
|
|
633
|
+
"data-testid": "login-passkey-direct",
|
|
634
|
+
onClick: async () => {
|
|
635
|
+
u(null), c(!0);
|
|
636
|
+
try {
|
|
637
|
+
let e = await R((await n.passkeyLoginBegin()).optionsJSON), t = await n.passkeyLoginFinish(e), i = t.secondFactors ?? (t.requiresTotp === !0 ? ["totp"] : []);
|
|
638
|
+
if (i.length > 0) {
|
|
639
|
+
if (r.onSecondFactor) r.onSecondFactor({
|
|
640
|
+
challengeToken: t.token,
|
|
641
|
+
factors: i
|
|
642
|
+
});
|
|
643
|
+
else {
|
|
644
|
+
let e = G(d, "secondFactorRequired");
|
|
645
|
+
u(e), r.onError?.(e);
|
|
646
|
+
}
|
|
647
|
+
return;
|
|
648
|
+
}
|
|
649
|
+
r.onComplete(t.token);
|
|
650
|
+
} catch (e) {
|
|
651
|
+
let t = e instanceof Error ? e.message : G(d, "failed");
|
|
652
|
+
u(t), r.onError?.(t);
|
|
653
|
+
} finally {
|
|
654
|
+
c(!1);
|
|
655
|
+
}
|
|
656
|
+
},
|
|
657
|
+
disabled: i,
|
|
658
|
+
className: "w-full flex items-center justify-center gap-2 rounded-lg border border-border bg-surface px-4 py-2.5 text-sm font-medium text-foreground hover:bg-surface-hover disabled:opacity-50 transition-colors",
|
|
659
|
+
children: [i ? /* @__PURE__ */ o(b, { className: "h-4 w-4 animate-spin text-primary" }) : /* @__PURE__ */ o(v, { className: "h-4 w-4 text-primary" }), G(d, "signInWithPasskey")]
|
|
660
|
+
}), l && /* @__PURE__ */ o("div", {
|
|
661
|
+
className: "rounded-md bg-danger/10 border border-danger/20 px-3 py-2 text-xs text-danger",
|
|
662
|
+
children: l
|
|
663
|
+
})]
|
|
664
|
+
}) : /* @__PURE__ */ o("div", {
|
|
665
|
+
className: "rounded-lg border border-border bg-surface px-3 py-2 text-xs text-foreground-subtle",
|
|
666
|
+
children: G(d, "unsupported")
|
|
667
|
+
}) : /* @__PURE__ */ o("div", {
|
|
668
|
+
className: "rounded-lg border border-warning/30 bg-warning/10 px-3 py-2 text-xs text-warning",
|
|
669
|
+
children: "Passkey direct-login widget requires an onComplete callback."
|
|
670
|
+
});
|
|
671
|
+
}
|
|
672
|
+
//#endregion
|
|
673
|
+
//#region src/webauthn/widgets/index.tsx
|
|
674
|
+
var J = {
|
|
564
675
|
"passkey-enrollment": B,
|
|
565
|
-
"passkey-login": H
|
|
676
|
+
"passkey-login": H,
|
|
677
|
+
"passkey-direct-login": q
|
|
566
678
|
};
|
|
567
679
|
//#endregion
|
|
568
|
-
export {
|
|
680
|
+
export { J as default };
|
|
@@ -3,7 +3,7 @@ import "./dist-CYZr2fwk.mjs";
|
|
|
3
3
|
var e = {
|
|
4
4
|
"@camstack/sdk": {
|
|
5
5
|
name: "@camstack/sdk",
|
|
6
|
-
version: "1.1.
|
|
6
|
+
version: "1.1.22",
|
|
7
7
|
scope: ["default"],
|
|
8
8
|
loaded: !1,
|
|
9
9
|
from: "addon_auth_webauthn_widgets",
|
|
@@ -18,7 +18,7 @@ var e = {
|
|
|
18
18
|
},
|
|
19
19
|
"@camstack/types": {
|
|
20
20
|
name: "@camstack/types",
|
|
21
|
-
version: "1.1.
|
|
21
|
+
version: "1.1.39",
|
|
22
22
|
scope: ["default"],
|
|
23
23
|
loaded: !1,
|
|
24
24
|
from: "addon_auth_webauthn_widgets",
|