@lumiapassport/ui-kit 1.4.6 → 1.4.8
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/iframe/main.js +1 -1
- package/dist/iframe/main.js.map +1 -1
- package/dist/index.cjs +62 -115
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +58 -111
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/dist/index.cjs
CHANGED
|
@@ -764,39 +764,31 @@ var init_passkey = __esm({
|
|
|
764
764
|
// src/internal/lib/iframe-mpc-client.ts
|
|
765
765
|
async function ensureDkgAndGetOwner(userId, _clientSeedHex) {
|
|
766
766
|
try {
|
|
767
|
-
console.info("[IframeMPC][DKG] Starting DKG via iframe for user:", userId);
|
|
768
767
|
const iframeManager = getIframeManager();
|
|
769
768
|
const keyshareStatus = await iframeManager.checkKeyshare(userId);
|
|
770
769
|
if (keyshareStatus.hasKeyshare && keyshareStatus.address) {
|
|
771
|
-
console.info("[IframeMPC][DKG] User already has keyshare in iframe:", {
|
|
772
|
-
userId,
|
|
773
|
-
address: keyshareStatus.address
|
|
774
|
-
});
|
|
775
770
|
return {
|
|
776
771
|
sessionId: "iframe-session",
|
|
777
772
|
ownerAddress: keyshareStatus.address
|
|
778
773
|
};
|
|
779
774
|
}
|
|
780
|
-
console.info("[IframeMPC][DKG] Authenticating user with iframe...");
|
|
781
775
|
await iframeManager.authenticate(userId);
|
|
782
776
|
const { jwtTokenManager: jwtTokenManager3 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
|
|
783
777
|
const accessToken = jwtTokenManager3.getAccessToken();
|
|
784
778
|
if (!accessToken) {
|
|
785
779
|
throw new Error("No access token available for DKG");
|
|
786
780
|
}
|
|
787
|
-
console.info("[IframeMPC][DKG] Starting DKG in iframe...");
|
|
788
781
|
const ownerAddress = await iframeManager.startDKG(userId, accessToken);
|
|
789
|
-
console.info("[IframeMPC][DKG] \u2705 DKG completed successfully:", {
|
|
790
|
-
userId,
|
|
791
|
-
ownerAddress,
|
|
792
|
-
note: "Key share is securely stored in iframe localStorage at auth.lumiapassport.com"
|
|
793
|
-
});
|
|
794
782
|
return {
|
|
795
783
|
sessionId: "iframe-session",
|
|
796
784
|
ownerAddress
|
|
797
785
|
};
|
|
798
786
|
} catch (error) {
|
|
799
|
-
|
|
787
|
+
(0, import_error_tracking.logSdkError)(
|
|
788
|
+
error instanceof Error ? error : new Error("DKG failed"),
|
|
789
|
+
{ userId },
|
|
790
|
+
"iframe-mpc"
|
|
791
|
+
);
|
|
800
792
|
throw error;
|
|
801
793
|
}
|
|
802
794
|
}
|
|
@@ -807,11 +799,6 @@ async function signDigestWithMpc(userId, digest32, userOpDetails) {
|
|
|
807
799
|
rounds: []
|
|
808
800
|
};
|
|
809
801
|
try {
|
|
810
|
-
console.info("[IframeMPC][Sign] Starting signature via iframe:", {
|
|
811
|
-
userId,
|
|
812
|
-
digest32: `${digest32.substring(0, 20)}...`,
|
|
813
|
-
hasDetails: !!userOpDetails
|
|
814
|
-
});
|
|
815
802
|
const iframeManager = getIframeManager();
|
|
816
803
|
const { jwtTokenManager: jwtTokenManager3 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
|
|
817
804
|
const accessToken = jwtTokenManager3.getAccessToken();
|
|
@@ -831,14 +818,13 @@ async function signDigestWithMpc(userId, digest32, userOpDetails) {
|
|
|
831
818
|
const endTime = performance.now();
|
|
832
819
|
currentSigningStats.endTime = endTime;
|
|
833
820
|
currentSigningStats.totalDurationMs = endTime - startTime;
|
|
834
|
-
console.info("[IframeMPC][Sign] \u2705 Signature obtained from iframe:", {
|
|
835
|
-
signature: `${signature.substring(0, 20)}...`,
|
|
836
|
-
duration: `${(endTime - startTime).toFixed(2)}ms`,
|
|
837
|
-
note: "All signing operations happened securely inside iframe"
|
|
838
|
-
});
|
|
839
821
|
return signature;
|
|
840
822
|
} catch (error) {
|
|
841
|
-
|
|
823
|
+
(0, import_error_tracking.logSdkError)(
|
|
824
|
+
error instanceof Error ? error : new Error("MPC signing failed"),
|
|
825
|
+
{ userId, hasUserOpDetails: !!userOpDetails },
|
|
826
|
+
"iframe-mpc"
|
|
827
|
+
);
|
|
842
828
|
const endTime = performance.now();
|
|
843
829
|
if (currentSigningStats) {
|
|
844
830
|
currentSigningStats.endTime = endTime;
|
|
@@ -856,10 +842,11 @@ async function checkKeyshare(userId) {
|
|
|
856
842
|
return { hasKeyshare: false };
|
|
857
843
|
}
|
|
858
844
|
}
|
|
859
|
-
var currentSigningStats;
|
|
845
|
+
var import_error_tracking, currentSigningStats;
|
|
860
846
|
var init_iframe_mpc_client = __esm({
|
|
861
847
|
"src/internal/lib/iframe-mpc-client.ts"() {
|
|
862
848
|
init_iframe_manager();
|
|
849
|
+
import_error_tracking = require("@lumiapassport/core/internal/error-tracking");
|
|
863
850
|
currentSigningStats = null;
|
|
864
851
|
}
|
|
865
852
|
});
|
|
@@ -868,12 +855,13 @@ var init_iframe_mpc_client = __esm({
|
|
|
868
855
|
function createHttpClient(baseUrl) {
|
|
869
856
|
return new HttpClient(baseUrl);
|
|
870
857
|
}
|
|
871
|
-
var HttpClient, _tssClient, _vaultClient, tssClient, vaultClient;
|
|
858
|
+
var import_error_tracking2, HttpClient, _tssClient, _vaultClient, tssClient, vaultClient;
|
|
872
859
|
var init_httpClient = __esm({
|
|
873
860
|
"src/internal/clients/httpClient.ts"() {
|
|
874
861
|
init_auth();
|
|
875
862
|
init_base();
|
|
876
863
|
init_projectId();
|
|
864
|
+
import_error_tracking2 = require("@lumiapassport/core/internal/error-tracking");
|
|
877
865
|
HttpClient = class {
|
|
878
866
|
constructor(baseUrl) {
|
|
879
867
|
this.baseUrl = baseUrl.replace(/\/$/, "");
|
|
@@ -903,14 +891,11 @@ var init_httpClient = __esm({
|
|
|
903
891
|
if (body && method !== "GET") {
|
|
904
892
|
requestConfig.body = typeof body === "string" ? body : JSON.stringify(body);
|
|
905
893
|
}
|
|
906
|
-
console.log(`[HttpClient] Making ${method} request to: ${url}`);
|
|
907
894
|
try {
|
|
908
895
|
const response = await fetch(url, requestConfig);
|
|
909
896
|
if (response.status === 401 && requireAuth) {
|
|
910
|
-
console.log("[HttpClient] Got 401, attempting token refresh...");
|
|
911
897
|
const refreshSuccess = await import_auth3.jwtTokenManager.refreshAccessToken();
|
|
912
898
|
if (refreshSuccess) {
|
|
913
|
-
console.log("[HttpClient] Token refreshed, retrying request...");
|
|
914
899
|
const newAccessToken = import_auth3.jwtTokenManager.getAccessToken();
|
|
915
900
|
if (newAccessToken) {
|
|
916
901
|
requestHeaders["Authorization"] = `Bearer ${newAccessToken}`;
|
|
@@ -919,7 +904,6 @@ var init_httpClient = __esm({
|
|
|
919
904
|
const retryResponse = await fetch(url, requestConfig);
|
|
920
905
|
return await this.processResponse(retryResponse);
|
|
921
906
|
} else {
|
|
922
|
-
console.error("[HttpClient] Token refresh failed");
|
|
923
907
|
return {
|
|
924
908
|
success: false,
|
|
925
909
|
error: "Authentication failed - unable to refresh token",
|
|
@@ -929,7 +913,11 @@ var init_httpClient = __esm({
|
|
|
929
913
|
}
|
|
930
914
|
return await this.processResponse(response);
|
|
931
915
|
} catch (error) {
|
|
932
|
-
|
|
916
|
+
(0, import_error_tracking2.logSdkError)(
|
|
917
|
+
error instanceof Error ? error : new Error("Network error"),
|
|
918
|
+
{ url, method },
|
|
919
|
+
"http-client"
|
|
920
|
+
);
|
|
933
921
|
return {
|
|
934
922
|
success: false,
|
|
935
923
|
error: error instanceof Error ? error.message : "Network error",
|
|
@@ -942,7 +930,6 @@ var init_httpClient = __esm({
|
|
|
942
930
|
try {
|
|
943
931
|
const data = await response.json();
|
|
944
932
|
if (!response.ok) {
|
|
945
|
-
console.log(`[HttpClient] Request failed with status ${status}:`, data);
|
|
946
933
|
return {
|
|
947
934
|
success: false,
|
|
948
935
|
error: data.message || data.error || `HTTP ${status}`,
|
|
@@ -950,14 +937,17 @@ var init_httpClient = __esm({
|
|
|
950
937
|
data
|
|
951
938
|
};
|
|
952
939
|
}
|
|
953
|
-
console.log(`[HttpClient] Request successful (${status})`);
|
|
954
940
|
return {
|
|
955
941
|
success: true,
|
|
956
942
|
data,
|
|
957
943
|
status
|
|
958
944
|
};
|
|
959
945
|
} catch (parseError) {
|
|
960
|
-
|
|
946
|
+
(0, import_error_tracking2.logSdkError)(
|
|
947
|
+
parseError instanceof Error ? parseError : new Error("Failed to parse response"),
|
|
948
|
+
{ status },
|
|
949
|
+
"http-client"
|
|
950
|
+
);
|
|
961
951
|
return {
|
|
962
952
|
success: false,
|
|
963
953
|
error: "Invalid response format",
|
|
@@ -1049,11 +1039,9 @@ var init_cloudStorage = __esm({
|
|
|
1049
1039
|
discoveryDocs: [this.DISCOVERY_DOC]
|
|
1050
1040
|
});
|
|
1051
1041
|
this.gapiInitialized = true;
|
|
1052
|
-
console.log("[GoogleDrive] Google API client initialized");
|
|
1053
1042
|
}
|
|
1054
1043
|
if (!this.gisInitialized) {
|
|
1055
1044
|
this.gisInitialized = true;
|
|
1056
|
-
console.log("[GoogleDrive] Google Identity Services initialized");
|
|
1057
1045
|
}
|
|
1058
1046
|
}
|
|
1059
1047
|
loadScript(src) {
|
|
@@ -1092,7 +1080,6 @@ var init_cloudStorage = __esm({
|
|
|
1092
1080
|
}
|
|
1093
1081
|
this.accessToken = response.access_token;
|
|
1094
1082
|
window.gapi.client.setToken({ access_token: this.accessToken });
|
|
1095
|
-
console.log("[GoogleDrive] Successfully authenticated");
|
|
1096
1083
|
resolve(true);
|
|
1097
1084
|
}
|
|
1098
1085
|
});
|
|
@@ -1111,7 +1098,6 @@ var init_cloudStorage = __esm({
|
|
|
1111
1098
|
window.google?.accounts.oauth2.revoke(this.accessToken);
|
|
1112
1099
|
this.accessToken = null;
|
|
1113
1100
|
window.gapi?.client.setToken(null);
|
|
1114
|
-
console.log("[GoogleDrive] Signed out successfully");
|
|
1115
1101
|
}
|
|
1116
1102
|
}
|
|
1117
1103
|
async upload(fileName, content, usePrivateStorage = true) {
|
|
@@ -1122,18 +1108,15 @@ var init_cloudStorage = __esm({
|
|
|
1122
1108
|
if (usePrivateStorage) {
|
|
1123
1109
|
try {
|
|
1124
1110
|
const fileId = await this.uploadToAppDataFolder(fileName, content);
|
|
1125
|
-
console.log("[GoogleDrive] File uploaded to appDataFolder successfully:", fileId);
|
|
1126
1111
|
return fileId;
|
|
1127
1112
|
} catch (error) {
|
|
1128
1113
|
console.warn("[GoogleDrive] AppDataFolder upload failed, trying fallback to regular folder:", error);
|
|
1129
1114
|
const fileId = await this.uploadToAppFolder(fileName, content);
|
|
1130
|
-
console.log("[GoogleDrive] File uploaded to app folder successfully:", fileId);
|
|
1131
1115
|
return fileId;
|
|
1132
1116
|
}
|
|
1133
1117
|
} else {
|
|
1134
1118
|
try {
|
|
1135
1119
|
const fileId = await this.uploadToAppFolder(fileName, content);
|
|
1136
|
-
console.log("[GoogleDrive] File uploaded to app folder successfully:", fileId);
|
|
1137
1120
|
return fileId;
|
|
1138
1121
|
} catch (error) {
|
|
1139
1122
|
console.error("[GoogleDrive] Upload failed:", error);
|
|
@@ -1189,7 +1172,6 @@ var init_cloudStorage = __esm({
|
|
|
1189
1172
|
throw new Error(`Failed to create folder: ${createResponse.status}`);
|
|
1190
1173
|
}
|
|
1191
1174
|
const createResult = await createResponse.json();
|
|
1192
|
-
console.log(`[GoogleDrive] Created folder '${folderName}':`, createResult.id);
|
|
1193
1175
|
return createResult.id;
|
|
1194
1176
|
}
|
|
1195
1177
|
async performUpload(metadata, content) {
|
|
@@ -1319,11 +1301,8 @@ async function deleteShare() {
|
|
|
1319
1301
|
if (!response.ok && response.status !== 404) throw new Error(`Failed to delete share: ${response.status} ${response.statusText}`);
|
|
1320
1302
|
}
|
|
1321
1303
|
async function deriveKEKFromPasskey(userId, requiredCredentialId) {
|
|
1322
|
-
console.log("[deriveKEKFromPasskey] Starting passkey derivation for userId:", userId);
|
|
1323
|
-
console.log("[deriveKEKFromPasskey] Required credential ID:", requiredCredentialId);
|
|
1324
1304
|
const challengeString = `lumia-kek:${userId}`;
|
|
1325
1305
|
const challenge = new TextEncoder().encode(challengeString);
|
|
1326
|
-
console.log("[deriveKEKFromPasskey] Challenge string:", challengeString);
|
|
1327
1306
|
function base64urlToUint8Array3(base64url) {
|
|
1328
1307
|
const base64 = base64url.replace(/-/g, "+").replace(/_/g, "/");
|
|
1329
1308
|
const pad = base64.length % 4 ? 4 - base64.length % 4 : 0;
|
|
@@ -1336,14 +1315,8 @@ async function deriveKEKFromPasskey(userId, requiredCredentialId) {
|
|
|
1336
1315
|
return bytes;
|
|
1337
1316
|
}
|
|
1338
1317
|
const targetCredentialId = requiredCredentialId || createPasskeyHelpers(userId).getCredId();
|
|
1339
|
-
console.log("[deriveKEKFromPasskey] Target credential ID:", targetCredentialId);
|
|
1340
1318
|
const allowCredentials = targetCredentialId ? [{ id: base64urlToUint8Array3(targetCredentialId), type: "public-key" }] : [];
|
|
1341
|
-
console.log("[deriveKEKFromPasskey] Using allowCredentials:", allowCredentials.length > 0 ? "specific credential" : "any credential");
|
|
1342
|
-
if (!targetCredentialId) {
|
|
1343
|
-
console.warn("[deriveKEKFromPasskey] Warning: No credential ID available. User must select the correct passkey manually.");
|
|
1344
|
-
}
|
|
1345
1319
|
try {
|
|
1346
|
-
console.log("[deriveKEKFromPasskey] Calling navigator.credentials.get...");
|
|
1347
1320
|
const credential = await navigator.credentials.get({
|
|
1348
1321
|
publicKey: {
|
|
1349
1322
|
challenge,
|
|
@@ -1352,27 +1325,22 @@ async function deriveKEKFromPasskey(userId, requiredCredentialId) {
|
|
|
1352
1325
|
extensions: { prf: { eval: { first: challenge } } }
|
|
1353
1326
|
}
|
|
1354
1327
|
});
|
|
1355
|
-
console.log("[deriveKEKFromPasskey] Credential received:", !!credential);
|
|
1356
1328
|
if (credential) {
|
|
1357
|
-
console.log("[deriveKEKFromPasskey] Credential ID:", credential.id);
|
|
1358
|
-
console.log("[deriveKEKFromPasskey] Credential ID length:", credential.id.length);
|
|
1359
1329
|
const extensionResults = credential.getClientExtensionResults?.();
|
|
1360
|
-
console.log("[deriveKEKFromPasskey] Extension results:", extensionResults);
|
|
1361
1330
|
if (extensionResults?.prf?.results?.first) {
|
|
1362
|
-
console.log("[deriveKEKFromPasskey] PRF result found, returning KEK");
|
|
1363
|
-
console.log("[deriveKEKFromPasskey] PRF result length:", extensionResults.prf.results.first.byteLength);
|
|
1364
1331
|
return extensionResults.prf.results.first;
|
|
1365
1332
|
}
|
|
1366
1333
|
}
|
|
1367
|
-
console.log("[deriveKEKFromPasskey] No PRF result, falling back to HKDF...");
|
|
1368
1334
|
const credentialIdBytes = new TextEncoder().encode(credential.id);
|
|
1369
|
-
console.log("[deriveKEKFromPasskey] Credential ID length:", credential.id.length);
|
|
1370
1335
|
const keyMaterial = await crypto.subtle.importKey("raw", credentialIdBytes, "HKDF", false, ["deriveBits"]);
|
|
1371
1336
|
const kekBytes = await crypto.subtle.deriveBits({ name: "HKDF", hash: "SHA-256", salt: challenge, info: new TextEncoder().encode("client-share") }, keyMaterial, 256);
|
|
1372
|
-
console.log("[deriveKEKFromPasskey] HKDF fallback completed successfully");
|
|
1373
1337
|
return kekBytes;
|
|
1374
1338
|
} catch (error) {
|
|
1375
|
-
|
|
1339
|
+
(0, import_error_tracking3.logSdkError)(
|
|
1340
|
+
error instanceof Error ? error : new Error("Passkey operation failed"),
|
|
1341
|
+
{ userId },
|
|
1342
|
+
"vault"
|
|
1343
|
+
);
|
|
1376
1344
|
throw error;
|
|
1377
1345
|
}
|
|
1378
1346
|
}
|
|
@@ -1457,7 +1425,6 @@ async function deriveBackupPasswordFromPasskey(userId, credentialId) {
|
|
|
1457
1425
|
type: "public-key",
|
|
1458
1426
|
transports: ["internal", "hybrid"]
|
|
1459
1427
|
}];
|
|
1460
|
-
console.log("[deriveBackupPasswordFromPasskey] Using specific credential ID:", credentialId);
|
|
1461
1428
|
} catch (error) {
|
|
1462
1429
|
console.warn("[deriveBackupPasswordFromPasskey] Failed to parse credentialId, falling back to open selection:", error);
|
|
1463
1430
|
}
|
|
@@ -1537,7 +1504,6 @@ async function downloadShareFromVault(token) {
|
|
|
1537
1504
|
async function envelopeEncryptKeyshare(data, userId) {
|
|
1538
1505
|
const passkeyHelpers = createPasskeyHelpers(userId);
|
|
1539
1506
|
const credentialId = passkeyHelpers.getCredId();
|
|
1540
|
-
console.log("[envelopeEncryptKeyshare] Using credential ID for encryption:", credentialId);
|
|
1541
1507
|
const dek = crypto.getRandomValues(new Uint8Array(32));
|
|
1542
1508
|
const kekBytes = await deriveKEKFromPasskey(userId);
|
|
1543
1509
|
const kek = await crypto.subtle.importKey("raw", kekBytes, "AES-GCM", false, ["encrypt"]);
|
|
@@ -1569,7 +1535,6 @@ async function envelopeEncryptKeyshare(data, userId) {
|
|
|
1569
1535
|
};
|
|
1570
1536
|
}
|
|
1571
1537
|
async function envelopeEncryptKeyshareWithPassword(data, password) {
|
|
1572
|
-
console.log("[envelopeEncryptKeyshareWithPassword] Encrypting with password");
|
|
1573
1538
|
const dek = crypto.getRandomValues(new Uint8Array(32));
|
|
1574
1539
|
const salt = crypto.getRandomValues(new Uint8Array(16));
|
|
1575
1540
|
const kekKey = await deriveKeyFromPassword(password, salt);
|
|
@@ -1600,39 +1565,27 @@ async function envelopeEncryptKeyshareWithPassword(data, password) {
|
|
|
1600
1565
|
};
|
|
1601
1566
|
}
|
|
1602
1567
|
async function envelopeDecryptKeyshare(envelope, userId) {
|
|
1603
|
-
console.log("[envelopeDecryptKeyshare] Starting decryption process");
|
|
1604
|
-
console.log("[envelopeDecryptKeyshare] Envelope credential ID:", envelope.credentialId);
|
|
1605
|
-
console.log("[envelopeDecryptKeyshare] Deriving KEK from passkey...");
|
|
1606
1568
|
const kekBytes = await deriveKEKFromPasskey(userId, envelope.credentialId);
|
|
1607
|
-
console.log("[envelopeDecryptKeyshare] KEK bytes length:", kekBytes.byteLength);
|
|
1608
|
-
console.log("[envelopeDecryptKeyshare] Importing KEK as crypto key...");
|
|
1609
1569
|
const kek = await crypto.subtle.importKey("raw", kekBytes, "AES-GCM", false, ["decrypt"]);
|
|
1610
|
-
console.log("[envelopeDecryptKeyshare] Decrypting wrapped DEK...");
|
|
1611
1570
|
const wrappedDekWithIv = base64ToBytes(envelope.wrapped_dek);
|
|
1612
|
-
console.log("[envelopeDecryptKeyshare] Wrapped DEK with IV length:", wrappedDekWithIv.length);
|
|
1613
1571
|
const wrapIv = wrappedDekWithIv.slice(0, 12);
|
|
1614
1572
|
const wrappedDekData = wrappedDekWithIv.slice(12);
|
|
1615
|
-
console.log("[envelopeDecryptKeyshare] Wrap IV length:", wrapIv.length, "Wrapped DEK data length:", wrappedDekData.length);
|
|
1616
1573
|
try {
|
|
1617
1574
|
const dekBytes = await crypto.subtle.decrypt({ name: "AES-GCM", iv: wrapIv }, kek, wrappedDekData);
|
|
1618
|
-
console.log("[envelopeDecryptKeyshare] DEK decrypted successfully, length:", dekBytes.byteLength);
|
|
1619
|
-
console.log("[envelopeDecryptKeyshare] Importing DEK as crypto key...");
|
|
1620
1575
|
const dekCryptoKey = await crypto.subtle.importKey("raw", dekBytes, "AES-GCM", false, ["decrypt"]);
|
|
1621
|
-
console.log("[envelopeDecryptKeyshare] Decrypting main data...");
|
|
1622
1576
|
const ciphertextWithIv = base64ToBytes(envelope.ciphertext_share);
|
|
1623
|
-
console.log("[envelopeDecryptKeyshare] Ciphertext with IV length:", ciphertextWithIv.length);
|
|
1624
1577
|
const dataIv = ciphertextWithIv.slice(0, 12);
|
|
1625
1578
|
const encryptedData = ciphertextWithIv.slice(12);
|
|
1626
|
-
console.log("[envelopeDecryptKeyshare] Data IV length:", dataIv.length, "Encrypted data length:", encryptedData.length);
|
|
1627
1579
|
const decryptedData = await crypto.subtle.decrypt({ name: "AES-GCM", iv: dataIv }, dekCryptoKey, encryptedData);
|
|
1628
|
-
console.log("[envelopeDecryptKeyshare] Main data decrypted successfully, length:", decryptedData.byteLength);
|
|
1629
|
-
console.log("[envelopeDecryptKeyshare] Parsing JSON...");
|
|
1630
1580
|
const plaintext = new TextDecoder().decode(decryptedData);
|
|
1631
1581
|
const result = JSON.parse(plaintext);
|
|
1632
|
-
console.log("[envelopeDecryptKeyshare] Decryption completed successfully");
|
|
1633
1582
|
return result;
|
|
1634
1583
|
} catch (error) {
|
|
1635
|
-
|
|
1584
|
+
(0, import_error_tracking3.logSdkError)(
|
|
1585
|
+
error instanceof Error ? error : new Error("Envelope decryption failed"),
|
|
1586
|
+
{ hasCredentialId: !!envelope.credentialId },
|
|
1587
|
+
"vault"
|
|
1588
|
+
);
|
|
1636
1589
|
if (error instanceof Error && error.name === "OperationError") {
|
|
1637
1590
|
const credentialHint = envelope.credentialId ? `The backup requires a specific passkey (ID: ${envelope.credentialId.slice(-8)}...)` : "The backup was encrypted with a different passkey than the one you selected";
|
|
1638
1591
|
throw new Error(`Passkey mismatch: ${credentialHint}. If you have multiple passkeys, please try again and select the correct passkey that was used when creating this backup.`);
|
|
@@ -1641,28 +1594,27 @@ async function envelopeDecryptKeyshare(envelope, userId) {
|
|
|
1641
1594
|
}
|
|
1642
1595
|
}
|
|
1643
1596
|
async function envelopeDecryptKeyshareWithPassword(envelope, password) {
|
|
1644
|
-
console.log("[envelopeDecryptKeyshareWithPassword] Starting password-based decryption");
|
|
1645
1597
|
const wrappedDekWithSaltAndIv = base64ToBytes(envelope.wrapped_dek);
|
|
1646
1598
|
const salt = wrappedDekWithSaltAndIv.slice(0, 16);
|
|
1647
1599
|
const wrapIv = wrappedDekWithSaltAndIv.slice(16, 28);
|
|
1648
1600
|
const wrappedDekData = wrappedDekWithSaltAndIv.slice(28);
|
|
1649
|
-
console.log("[envelopeDecryptKeyshareWithPassword] Salt length:", salt.length, "Wrap IV length:", wrapIv.length, "Wrapped DEK data length:", wrappedDekData.length);
|
|
1650
1601
|
try {
|
|
1651
1602
|
const kekKey = await deriveKeyFromPassword(password, salt);
|
|
1652
1603
|
const dekBytes = await crypto.subtle.decrypt({ name: "AES-GCM", iv: wrapIv }, kekKey, wrappedDekData);
|
|
1653
|
-
console.log("[envelopeDecryptKeyshareWithPassword] DEK decrypted successfully, length:", dekBytes.byteLength);
|
|
1654
1604
|
const dekCryptoKey = await crypto.subtle.importKey("raw", dekBytes, "AES-GCM", false, ["decrypt"]);
|
|
1655
1605
|
const ciphertextWithIv = base64ToBytes(envelope.ciphertext_share);
|
|
1656
1606
|
const dataIv = ciphertextWithIv.slice(0, 12);
|
|
1657
1607
|
const encryptedData = ciphertextWithIv.slice(12);
|
|
1658
1608
|
const decryptedData = await crypto.subtle.decrypt({ name: "AES-GCM", iv: dataIv }, dekCryptoKey, encryptedData);
|
|
1659
|
-
console.log("[envelopeDecryptKeyshareWithPassword] Main data decrypted successfully");
|
|
1660
1609
|
const plaintext = new TextDecoder().decode(decryptedData);
|
|
1661
1610
|
const result = JSON.parse(plaintext);
|
|
1662
|
-
console.log("[envelopeDecryptKeyshareWithPassword] Decryption completed successfully");
|
|
1663
1611
|
return result;
|
|
1664
1612
|
} catch (error) {
|
|
1665
|
-
|
|
1613
|
+
(0, import_error_tracking3.logSdkError)(
|
|
1614
|
+
error instanceof Error ? error : new Error("Password decryption failed"),
|
|
1615
|
+
{ errorName: error instanceof Error ? error.name : "unknown" },
|
|
1616
|
+
"vault"
|
|
1617
|
+
);
|
|
1666
1618
|
if (error instanceof Error && error.name === "OperationError") {
|
|
1667
1619
|
throw new Error("Incorrect password: Unable to decrypt the backup with the provided password.");
|
|
1668
1620
|
}
|
|
@@ -1682,22 +1634,15 @@ async function backupToServer(userId, password) {
|
|
|
1682
1634
|
updateBackupStatus(userId, "server", { enabled: true, lastBackup: Date.now(), error: void 0 });
|
|
1683
1635
|
}
|
|
1684
1636
|
async function restoreFromServer(userId, password = null) {
|
|
1685
|
-
console.log("[restoreFromServer] Starting restore for userId:", userId);
|
|
1686
|
-
console.log("[restoreFromServer] Using password:", !!password);
|
|
1687
|
-
console.log("[restoreFromServer] Getting vault token...");
|
|
1688
1637
|
const vaultToken = await getShareVaultToken(["share:get"]);
|
|
1689
|
-
console.log("[restoreFromServer] Downloading share from vault...");
|
|
1690
1638
|
const envelope = await downloadShareFromVault(vaultToken.token);
|
|
1691
|
-
console.log("[restoreFromServer] Envelope encryption method:", envelope.encryptionMethod);
|
|
1692
1639
|
const backupData = password ? await envelopeDecryptKeyshareWithPassword(envelope, password) : await envelopeDecryptKeyshare(envelope, userId);
|
|
1693
1640
|
if (backupData.userId !== userId) throw new Error("Server backup does not match current user");
|
|
1694
1641
|
const storage = typeof window !== "undefined" ? window.localStorage : void 0;
|
|
1695
1642
|
if (!storage) throw new Error("localStorage not available");
|
|
1696
|
-
console.log("[restoreFromServer] Saving keyshare to localStorage...");
|
|
1697
1643
|
storage.setItem(`tss.${userId}.keyshare`, backupData.keyshare);
|
|
1698
1644
|
storage.setItem(`tss.${userId}.sessionId`, backupData.sessionId);
|
|
1699
1645
|
storage.setItem(`tss.${userId}.ownerAddress`, backupData.ownerAddress);
|
|
1700
|
-
console.log("[restoreFromServer] Restore completed successfully");
|
|
1701
1646
|
}
|
|
1702
1647
|
async function restoreFromBackup(file, password, userId) {
|
|
1703
1648
|
const fileContent = await file.text();
|
|
@@ -1743,7 +1688,11 @@ function getCurrentKeyshareBackupData(userId) {
|
|
|
1743
1688
|
version: BACKUP_VERSION
|
|
1744
1689
|
};
|
|
1745
1690
|
} catch (error) {
|
|
1746
|
-
|
|
1691
|
+
(0, import_error_tracking3.logSdkError)(
|
|
1692
|
+
error instanceof Error ? error : new Error("Failed to get keyshare data"),
|
|
1693
|
+
{ userId },
|
|
1694
|
+
"vault"
|
|
1695
|
+
);
|
|
1747
1696
|
return null;
|
|
1748
1697
|
}
|
|
1749
1698
|
}
|
|
@@ -1763,7 +1712,6 @@ async function backupToLocalFile(userId, password) {
|
|
|
1763
1712
|
});
|
|
1764
1713
|
backupPassword = result.password;
|
|
1765
1714
|
credentialId = result.credentialId;
|
|
1766
|
-
console.log("[backupToLocalFile] Using credential ID from passkey:", credentialId);
|
|
1767
1715
|
}
|
|
1768
1716
|
const encryptedBackup = await encryptKeyshare(backupData, backupPassword, encryptionMethod, credentialId);
|
|
1769
1717
|
const fileName = `lumia-keyshare-backup-${userId}-${Date.now()}.json`;
|
|
@@ -1796,7 +1744,6 @@ async function backupToCloud(userId, password, providerId, usePrivateStorage = t
|
|
|
1796
1744
|
});
|
|
1797
1745
|
backupPassword = result.password;
|
|
1798
1746
|
credentialId = result.credentialId;
|
|
1799
|
-
console.log("[backupToCloud] Using credential ID from passkey:", credentialId);
|
|
1800
1747
|
}
|
|
1801
1748
|
const encryptedBackup = await encryptKeyshare(backupData, backupPassword, encryptionMethod, credentialId);
|
|
1802
1749
|
const timestamp = Date.now();
|
|
@@ -1827,9 +1774,12 @@ async function backupToCloud(userId, password, providerId, usePrivateStorage = t
|
|
|
1827
1774
|
console.info(`[BACKUP] Uploading backup to ${provider.name}`);
|
|
1828
1775
|
const fileId = await provider.upload(fileName, fileContent, usePrivateStorage);
|
|
1829
1776
|
updateBackupStatus(userId, "cloud", { enabled: true, lastBackup: timestamp, error: void 0 });
|
|
1830
|
-
console.info(`[BACKUP] Successfully uploaded backup to ${provider.name}, file ID: ${fileId}`);
|
|
1831
1777
|
} catch (error) {
|
|
1832
|
-
|
|
1778
|
+
(0, import_error_tracking3.logSdkError)(
|
|
1779
|
+
error instanceof Error ? error : new Error("Cloud backup failed"),
|
|
1780
|
+
{ userId, providerId },
|
|
1781
|
+
"vault"
|
|
1782
|
+
);
|
|
1833
1783
|
const errorMsg = error instanceof Error ? error.message : "Cloud backup failed";
|
|
1834
1784
|
updateBackupStatus(userId, "cloud", { error: errorMsg });
|
|
1835
1785
|
throw new Error(errorMsg);
|
|
@@ -1850,12 +1800,13 @@ async function getAvailableCloudProviders2() {
|
|
|
1850
1800
|
return [];
|
|
1851
1801
|
}
|
|
1852
1802
|
}
|
|
1853
|
-
var PasswordValidationError, BACKUP_MAGIC, BACKUP_VERSION;
|
|
1803
|
+
var import_error_tracking3, PasswordValidationError, BACKUP_MAGIC, BACKUP_VERSION;
|
|
1854
1804
|
var init_vaultClient = __esm({
|
|
1855
1805
|
"src/internal/vaultClient.ts"() {
|
|
1856
1806
|
init_base();
|
|
1857
1807
|
init_httpClient();
|
|
1858
1808
|
init_passkey();
|
|
1809
|
+
import_error_tracking3 = require("@lumiapassport/core/internal/error-tracking");
|
|
1859
1810
|
PasswordValidationError = class extends Error {
|
|
1860
1811
|
constructor(message) {
|
|
1861
1812
|
super(message);
|
|
@@ -2958,13 +2909,14 @@ var init_iframe_manager = __esm({
|
|
|
2958
2909
|
});
|
|
2959
2910
|
|
|
2960
2911
|
// src/context/LumiaPassportContext.tsx
|
|
2961
|
-
var import_react, import_jsx_runtime3, LumiaPassportContext, LumiaPassportProvider, useLumiaPassportConfig;
|
|
2912
|
+
var import_react, import_error_tracking4, import_jsx_runtime3, LumiaPassportContext, LumiaPassportProvider, useLumiaPassportConfig;
|
|
2962
2913
|
var init_LumiaPassportContext = __esm({
|
|
2963
2914
|
"src/context/LumiaPassportContext.tsx"() {
|
|
2964
2915
|
import_react = require("react");
|
|
2965
2916
|
init_lumiaPassport();
|
|
2966
2917
|
init_WagmiContext();
|
|
2967
2918
|
init_iframe_manager();
|
|
2919
|
+
import_error_tracking4 = require("@lumiapassport/core/internal/error-tracking");
|
|
2968
2920
|
import_jsx_runtime3 = require("react/jsx-runtime");
|
|
2969
2921
|
LumiaPassportContext = (0, import_react.createContext)(void 0);
|
|
2970
2922
|
LumiaPassportProvider = ({
|
|
@@ -3024,6 +2976,13 @@ var init_LumiaPassportContext = __esm({
|
|
|
3024
2976
|
}
|
|
3025
2977
|
} catch {
|
|
3026
2978
|
}
|
|
2979
|
+
try {
|
|
2980
|
+
(0, import_error_tracking4.initSdkErrorTracking)();
|
|
2981
|
+
} catch (error) {
|
|
2982
|
+
if (process.env.NODE_ENV === "development") {
|
|
2983
|
+
console.warn("[LumiaPassport] Failed to initialize SDK error tracking:", error);
|
|
2984
|
+
}
|
|
2985
|
+
}
|
|
3027
2986
|
return merged;
|
|
3028
2987
|
});
|
|
3029
2988
|
const updateConfig = (0, import_react.useCallback)((updates) => {
|
|
@@ -4093,25 +4052,19 @@ var init_VerificationCodeInput = __esm({
|
|
|
4093
4052
|
|
|
4094
4053
|
// src/internal/clients/profile.ts
|
|
4095
4054
|
async function getUserProfile() {
|
|
4096
|
-
console.log("[ProfileClient] Fetching user profile...");
|
|
4097
4055
|
const response = await tssClient.get("/api/auth/profile", true);
|
|
4098
4056
|
if (!response.success || !response.data) {
|
|
4099
4057
|
const error = response.error || "Failed to fetch user profile";
|
|
4100
|
-
console.error("[ProfileClient] Failed to fetch profile:", error);
|
|
4101
4058
|
throw new Error(error);
|
|
4102
4059
|
}
|
|
4103
|
-
console.log("[ProfileClient] Profile fetched successfully:", response.data);
|
|
4104
4060
|
return response.data;
|
|
4105
4061
|
}
|
|
4106
4062
|
async function updateUserProfile(updates) {
|
|
4107
|
-
console.log("[ProfileClient] Updating user profile:", updates);
|
|
4108
4063
|
const response = await tssClient.patch("/api/auth/profile", updates, true);
|
|
4109
4064
|
if (!response.success || !response.data) {
|
|
4110
4065
|
const error = response.error || "Failed to update user profile";
|
|
4111
|
-
console.error("[ProfileClient] Failed to update profile:", error);
|
|
4112
4066
|
throw new Error(error);
|
|
4113
4067
|
}
|
|
4114
|
-
console.log("[ProfileClient] Profile updated successfully:", response.data);
|
|
4115
4068
|
return response.data;
|
|
4116
4069
|
}
|
|
4117
4070
|
var init_profile = __esm({
|
|
@@ -5286,10 +5239,7 @@ async function sendUserOperation(session, callTarget, amountWei, innerData = "0x
|
|
|
5286
5239
|
paymasterAndData = `0x${paymasterAddr}${packedPaymasterGasLimits.slice(2)}${paymasterDataClean}`;
|
|
5287
5240
|
}
|
|
5288
5241
|
const packedForHash = { sender: session.smartAccountAddress, nonce: BigInt(nonce2), initCode, callData, accountGasLimits, preVerificationGas: BigInt(userOp.preVerificationGas), gasFees, paymasterAndData, signature: "0x" };
|
|
5289
|
-
console.log("[Account] Computing hash for signing with sender:", session.smartAccountAddress);
|
|
5290
|
-
console.log("[Account] PackedForHash for hash computation:", JSON.stringify(packedForHash, (key, value) => typeof value === "bigint" ? `0x${value.toString(16)}` : value, 2));
|
|
5291
5242
|
opHash = await publicClient.readContract({ address: entryPointAddress, abi: import_account_abstraction2.entryPoint07Abi, functionName: "getUserOpHash", args: [packedForHash] });
|
|
5292
|
-
console.log("[Account] \u{1F511} HASH FOR SIGNING:", opHash);
|
|
5293
5243
|
}
|
|
5294
5244
|
let signature;
|
|
5295
5245
|
if (session.mpcUserId) {
|
|
@@ -5317,10 +5267,8 @@ async function sendUserOperation(session, callTarget, amountWei, innerData = "0x
|
|
|
5317
5267
|
}
|
|
5318
5268
|
userOp.signature = signature;
|
|
5319
5269
|
if (typeof userOp.sender !== "string") {
|
|
5320
|
-
console.error("[Account] CRITICAL ERROR: userOp.sender is not a string!", userOp.sender);
|
|
5321
5270
|
userOp.sender = session.smartAccountAddress;
|
|
5322
5271
|
}
|
|
5323
|
-
console.log("[Account] \u2705 Final UserOp before sending:", JSON.stringify(userOp, (key, value) => typeof value === "bigint" ? `0x${value.toString(16)}` : value, 2));
|
|
5324
5272
|
return userOp;
|
|
5325
5273
|
};
|
|
5326
5274
|
try {
|
|
@@ -5535,8 +5483,6 @@ async function prepareUserOperation(session, callTarget, amountWei, innerData =
|
|
|
5535
5483
|
if (typeof userOp.sender !== "string") {
|
|
5536
5484
|
userOp.sender = session.smartAccountAddress;
|
|
5537
5485
|
}
|
|
5538
|
-
console.log("[Account] \u2705 Prepared signed UserOp (not sent):", JSON.stringify(userOp, (key, value) => typeof value === "bigint" ? `0x${value.toString(16)}` : value, 2));
|
|
5539
|
-
console.log("[Account] \u{1F511} UserOp Hash:", opHash);
|
|
5540
5486
|
if (entryPointVersion === "v0.6") {
|
|
5541
5487
|
const userOpV06 = convertUserOpV07ToV06(userOp);
|
|
5542
5488
|
return { userOp: userOpV06, userOpHash: opHash };
|
|
@@ -8592,7 +8538,7 @@ function useLumiaPassportLinkedProfiles() {
|
|
|
8592
8538
|
// package.json
|
|
8593
8539
|
var package_default = {
|
|
8594
8540
|
name: "@lumiapassport/ui-kit",
|
|
8595
|
-
version: "1.4.
|
|
8541
|
+
version: "1.4.8",
|
|
8596
8542
|
description: "React UI components and hooks for Lumia Passport authentication and Account Abstraction",
|
|
8597
8543
|
type: "module",
|
|
8598
8544
|
main: "./dist/index.cjs",
|
|
@@ -8643,6 +8589,7 @@ var package_default = {
|
|
|
8643
8589
|
dependencies: {
|
|
8644
8590
|
"@lumiapassport/core": "workspace:*",
|
|
8645
8591
|
"@rainbow-me/rainbowkit": "^2.2.8",
|
|
8592
|
+
"@sentry/browser": "^10.22.0",
|
|
8646
8593
|
"lucide-react": "^0.454.0",
|
|
8647
8594
|
qrcode: "^1.5.0"
|
|
8648
8595
|
},
|