Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
58d9b4386e | ||
|
|
cb4f4b2a3c | ||
|
|
05a5306f86 | ||
|
|
98b87de736 | ||
|
|
ae6f176f52 | ||
|
|
a79277f3ed |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -19,3 +19,4 @@ log.txt
|
|||||||
Trash/
|
Trash/
|
||||||
|
|
||||||
nostr-login/
|
nostr-login/
|
||||||
|
nostr-tools/
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
* Two-file architecture:
|
* Two-file architecture:
|
||||||
* 1. Load nostr.bundle.js (official nostr-tools bundle)
|
* 1. Load nostr.bundle.js (official nostr-tools bundle)
|
||||||
* 2. Load nostr-lite.js (this file - NOSTR_LOGIN_LITE library with CSS-only themes)
|
* 2. Load nostr-lite.js (this file - NOSTR_LOGIN_LITE library with CSS-only themes)
|
||||||
* Generated on: 2025-09-24T14:50:11.123Z
|
* Generated on: 2025-11-14T18:40:05.334Z
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Verify dependencies are loaded
|
// Verify dependencies are loaded
|
||||||
@@ -18,10 +18,10 @@ if (typeof window !== 'undefined') {
|
|||||||
throw new Error('Missing dependency: nostr.bundle.js');
|
throw new Error('Missing dependency: nostr.bundle.js');
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('NOSTR_LOGIN_LITE: Dependencies verified ✓');
|
// console.log('NOSTR_LOGIN_LITE: Dependencies verified ✓');
|
||||||
console.log('NOSTR_LOGIN_LITE: NostrTools available with keys:', Object.keys(window.NostrTools));
|
// console.log('NOSTR_LOGIN_LITE: NostrTools available with keys:', Object.keys(window.NostrTools));
|
||||||
console.log('NOSTR_LOGIN_LITE: NIP-06 available:', !!window.NostrTools.nip06);
|
// console.log('NOSTR_LOGIN_LITE: NIP-06 available:', !!window.NostrTools.nip06);
|
||||||
console.log('NOSTR_LOGIN_LITE: NIP-46 available:', !!window.NostrTools.nip46);
|
// console.log('NOSTR_LOGIN_LITE: NIP-46 available:', !!window.NostrTools.nip46);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ======================================
|
// ======================================
|
||||||
@@ -282,7 +282,7 @@ function injectThemeCSS(themeName = 'default') {
|
|||||||
style.id = 'nl-theme-css';
|
style.id = 'nl-theme-css';
|
||||||
style.textContent = themeCss;
|
style.textContent = themeCss;
|
||||||
document.head.appendChild(style);
|
document.head.appendChild(style);
|
||||||
console.log('NOSTR_LOGIN_LITE: ' + themeName + ' theme CSS injected');
|
// console.log('NOSTR_LOGIN_LITE: ' + themeName + ' theme CSS injected');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -436,7 +436,7 @@ class Modal {
|
|||||||
modalContent.appendChild(modalHeader);
|
modalContent.appendChild(modalHeader);
|
||||||
// Add version element in bottom-right corner aligned with modal body
|
// Add version element in bottom-right corner aligned with modal body
|
||||||
const versionElement = document.createElement('div');
|
const versionElement = document.createElement('div');
|
||||||
versionElement.textContent = 'v0.1.6';
|
versionElement.textContent = 'v0.1.12';
|
||||||
versionElement.style.cssText = `
|
versionElement.style.cssText = `
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 8px;
|
bottom: 8px;
|
||||||
@@ -642,7 +642,7 @@ class Modal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_handleOptionClick(type) {
|
_handleOptionClick(type) {
|
||||||
console.log('Selected login type:', type);
|
// console.log('Selected login type:', type);
|
||||||
|
|
||||||
// Handle different login types
|
// Handle different login types
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@@ -674,16 +674,16 @@ class Modal {
|
|||||||
// Check if NostrLite instance has a preserved extension (real extension detected at init)
|
// Check if NostrLite instance has a preserved extension (real extension detected at init)
|
||||||
if (window.NOSTR_LOGIN_LITE?._instance?.preservedExtension) {
|
if (window.NOSTR_LOGIN_LITE?._instance?.preservedExtension) {
|
||||||
extension = window.NOSTR_LOGIN_LITE._instance.preservedExtension;
|
extension = window.NOSTR_LOGIN_LITE._instance.preservedExtension;
|
||||||
console.log('Modal: Using preserved extension:', extension.constructor?.name);
|
// console.log('Modal: Using preserved extension:', extension.constructor?.name);
|
||||||
}
|
}
|
||||||
// Otherwise check current window.nostr
|
// Otherwise check current window.nostr
|
||||||
else if (window.nostr && this._isRealExtension(window.nostr)) {
|
else if (window.nostr && this._isRealExtension(window.nostr)) {
|
||||||
extension = window.nostr;
|
extension = window.nostr;
|
||||||
console.log('Modal: Using current window.nostr extension:', extension.constructor?.name);
|
// console.log('Modal: Using current window.nostr extension:', extension.constructor?.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!extension) {
|
if (!extension) {
|
||||||
console.log('Modal: No extension detected yet, waiting for deferred detection...');
|
// console.log('Modal: No extension detected yet, waiting for deferred detection...');
|
||||||
|
|
||||||
// DEFERRED EXTENSION CHECK: Extensions like nos2x might load after our library
|
// DEFERRED EXTENSION CHECK: Extensions like nos2x might load after our library
|
||||||
let attempts = 0;
|
let attempts = 0;
|
||||||
@@ -694,7 +694,7 @@ class Modal {
|
|||||||
// Check again for preserved extension (might be set by deferred detection)
|
// Check again for preserved extension (might be set by deferred detection)
|
||||||
if (window.NOSTR_LOGIN_LITE?._instance?.preservedExtension) {
|
if (window.NOSTR_LOGIN_LITE?._instance?.preservedExtension) {
|
||||||
extension = window.NOSTR_LOGIN_LITE._instance.preservedExtension;
|
extension = window.NOSTR_LOGIN_LITE._instance.preservedExtension;
|
||||||
console.log('Modal: Found preserved extension after waiting:', extension.constructor?.name);
|
// console.log('Modal: Found preserved extension after waiting:', extension.constructor?.name);
|
||||||
this._tryExtensionLogin(extension);
|
this._tryExtensionLogin(extension);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -702,7 +702,7 @@ class Modal {
|
|||||||
// Check current window.nostr again
|
// Check current window.nostr again
|
||||||
if (window.nostr && this._isRealExtension(window.nostr)) {
|
if (window.nostr && this._isRealExtension(window.nostr)) {
|
||||||
extension = window.nostr;
|
extension = window.nostr;
|
||||||
console.log('Modal: Found extension at window.nostr after waiting:', extension.constructor?.name);
|
// console.log('Modal: Found extension at window.nostr after waiting:', extension.constructor?.name);
|
||||||
this._tryExtensionLogin(extension);
|
this._tryExtensionLogin(extension);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -711,7 +711,7 @@ class Modal {
|
|||||||
if (attempts < maxAttempts) {
|
if (attempts < maxAttempts) {
|
||||||
setTimeout(checkForExtension, 200);
|
setTimeout(checkForExtension, 200);
|
||||||
} else {
|
} else {
|
||||||
console.log('Modal: No browser extension found after waiting 2 seconds');
|
// console.log('Modal: No browser extension found after waiting 2 seconds');
|
||||||
this._showExtensionRequired();
|
this._showExtensionRequired();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -722,7 +722,7 @@ class Modal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use the single detected extension directly - no choice UI
|
// Use the single detected extension directly - no choice UI
|
||||||
console.log('Modal: Single extension mode - using extension directly');
|
// console.log('Modal: Single extension mode - using extension directly');
|
||||||
this._tryExtensionLogin(extension);
|
this._tryExtensionLogin(extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -747,7 +747,7 @@ class Modal {
|
|||||||
try {
|
try {
|
||||||
const obj = location.getter();
|
const obj = location.getter();
|
||||||
|
|
||||||
console.log(`Modal: Checking ${location.name}:`, !!obj, obj?.constructor?.name);
|
// console.log(`Modal: Checking ${location.name}:`, !!obj, obj?.constructor?.name);
|
||||||
|
|
||||||
if (obj && this._isRealExtension(obj) && !seenExtensions.has(obj)) {
|
if (obj && this._isRealExtension(obj) && !seenExtensions.has(obj)) {
|
||||||
extensions.push({
|
extensions.push({
|
||||||
@@ -757,25 +757,25 @@ class Modal {
|
|||||||
extension: obj
|
extension: obj
|
||||||
});
|
});
|
||||||
seenExtensions.add(obj);
|
seenExtensions.add(obj);
|
||||||
console.log(`Modal: ✓ Detected extension at ${location.name} (${obj.constructor?.name})`);
|
// console.log(`Modal: ✓ Detected extension at ${location.name} (${obj.constructor?.name})`);
|
||||||
} else if (obj) {
|
} else if (obj) {
|
||||||
console.log(`Modal: ✗ Filtered out ${location.name} (${obj.constructor?.name})`);
|
// console.log(`Modal: ✗ Filtered out ${location.name} (${obj.constructor?.name})`);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Location doesn't exist or can't be accessed
|
// Location doesn't exist or can't be accessed
|
||||||
console.log(`Modal: ${location.name} not accessible:`, e.message);
|
// console.log(`Modal: ${location.name} not accessible:`, e.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Also check window.nostr but be extra careful to avoid our library
|
// Also check window.nostr but be extra careful to avoid our library
|
||||||
console.log('Modal: Checking window.nostr:', !!window.nostr, window.nostr?.constructor?.name);
|
// console.log('Modal: Checking window.nostr:', !!window.nostr, window.nostr?.constructor?.name);
|
||||||
|
|
||||||
if (window.nostr) {
|
if (window.nostr) {
|
||||||
// Check if window.nostr is our WindowNostr facade with a preserved extension
|
// Check if window.nostr is our WindowNostr facade with a preserved extension
|
||||||
if (window.nostr.constructor?.name === 'WindowNostr' && window.nostr.existingNostr) {
|
if (window.nostr.constructor?.name === 'WindowNostr' && window.nostr.existingNostr) {
|
||||||
console.log('Modal: Found WindowNostr facade, checking existingNostr for preserved extension');
|
// console.log('Modal: Found WindowNostr facade, checking existingNostr for preserved extension');
|
||||||
const preservedExtension = window.nostr.existingNostr;
|
const preservedExtension = window.nostr.existingNostr;
|
||||||
console.log('Modal: Preserved extension:', !!preservedExtension, preservedExtension?.constructor?.name);
|
// console.log('Modal: Preserved extension:', !!preservedExtension, preservedExtension?.constructor?.name);
|
||||||
|
|
||||||
if (preservedExtension && this._isRealExtension(preservedExtension) && !seenExtensions.has(preservedExtension)) {
|
if (preservedExtension && this._isRealExtension(preservedExtension) && !seenExtensions.has(preservedExtension)) {
|
||||||
extensions.push({
|
extensions.push({
|
||||||
@@ -785,7 +785,7 @@ class Modal {
|
|||||||
extension: preservedExtension
|
extension: preservedExtension
|
||||||
});
|
});
|
||||||
seenExtensions.add(preservedExtension);
|
seenExtensions.add(preservedExtension);
|
||||||
console.log(`Modal: ✓ Detected preserved extension: ${preservedExtension.constructor?.name}`);
|
// console.log(`Modal: ✓ Detected preserved extension: ${preservedExtension.constructor?.name}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check if window.nostr is directly a real extension (not our facade)
|
// Check if window.nostr is directly a real extension (not our facade)
|
||||||
@@ -797,9 +797,9 @@ class Modal {
|
|||||||
extension: window.nostr
|
extension: window.nostr
|
||||||
});
|
});
|
||||||
seenExtensions.add(window.nostr);
|
seenExtensions.add(window.nostr);
|
||||||
console.log(`Modal: ✓ Detected extension at window.nostr: ${window.nostr.constructor?.name}`);
|
// console.log(`Modal: ✓ Detected extension at window.nostr: ${window.nostr.constructor?.name}`);
|
||||||
} else {
|
} else {
|
||||||
console.log(`Modal: ✗ Filtered out window.nostr (${window.nostr.constructor?.name}) - not a real extension`);
|
// console.log(`Modal: ✗ Filtered out window.nostr (${window.nostr.constructor?.name}) - not a real extension`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -807,27 +807,27 @@ class Modal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_isRealExtension(obj) {
|
_isRealExtension(obj) {
|
||||||
console.log(`Modal: EXTENSIVE DEBUG - _isRealExtension called with:`, obj);
|
// console.log(`Modal: EXTENSIVE DEBUG - _isRealExtension called with:`, obj);
|
||||||
console.log(`Modal: Object type: ${typeof obj}`);
|
// console.log(`Modal: Object type: ${typeof obj}`);
|
||||||
console.log(`Modal: Object truthy: ${!!obj}`);
|
// console.log(`Modal: Object truthy: ${!!obj}`);
|
||||||
|
|
||||||
if (!obj || typeof obj !== 'object') {
|
if (!obj || typeof obj !== 'object') {
|
||||||
console.log(`Modal: REJECT - Not an object`);
|
// console.log(`Modal: REJECT - Not an object`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`Modal: getPublicKey type: ${typeof obj.getPublicKey}`);
|
// console.log(`Modal: getPublicKey type: ${typeof obj.getPublicKey}`);
|
||||||
console.log(`Modal: signEvent type: ${typeof obj.signEvent}`);
|
// console.log(`Modal: signEvent type: ${typeof obj.signEvent}`);
|
||||||
|
|
||||||
// Must have required Nostr methods
|
// Must have required Nostr methods
|
||||||
if (typeof obj.getPublicKey !== 'function' || typeof obj.signEvent !== 'function') {
|
if (typeof obj.getPublicKey !== 'function' || typeof obj.signEvent !== 'function') {
|
||||||
console.log(`Modal: REJECT - Missing required methods`);
|
// console.log(`Modal: REJECT - Missing required methods`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exclude NostrTools library object
|
// Exclude NostrTools library object
|
||||||
if (obj === window.NostrTools) {
|
if (obj === window.NostrTools) {
|
||||||
console.log(`Modal: REJECT - Is NostrTools object`);
|
// console.log(`Modal: REJECT - Is NostrTools object`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -836,8 +836,8 @@ class Modal {
|
|||||||
const constructorName = obj.constructor?.name;
|
const constructorName = obj.constructor?.name;
|
||||||
const objectKeys = Object.keys(obj);
|
const objectKeys = Object.keys(obj);
|
||||||
|
|
||||||
console.log(`Modal: Constructor name: "${constructorName}"`);
|
// console.log(`Modal: Constructor name: "${constructorName}"`);
|
||||||
console.log(`Modal: Object keys: [${objectKeys.join(', ')}]`);
|
// console.log(`Modal: Object keys: [${objectKeys.join(', ')}]`);
|
||||||
|
|
||||||
// COMPREHENSIVE TEST LOGIC - Accept anything with required methods that's not our specific library classes
|
// COMPREHENSIVE TEST LOGIC - Accept anything with required methods that's not our specific library classes
|
||||||
const isRealExtension = (
|
const isRealExtension = (
|
||||||
@@ -847,12 +847,12 @@ class Modal {
|
|||||||
constructorName !== 'NostrLite' // Our main class
|
constructorName !== 'NostrLite' // Our main class
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log(`Modal: Using comprehensive test logic:`);
|
// console.log(`Modal: Using comprehensive test logic:`);
|
||||||
console.log(` Has getPublicKey: ${typeof obj.getPublicKey === 'function'}`);
|
// console.log(` Has getPublicKey: ${typeof obj.getPublicKey === 'function'}`);
|
||||||
console.log(` Has signEvent: ${typeof obj.signEvent === 'function'}`);
|
// console.log(` Has signEvent: ${typeof obj.signEvent === 'function'}`);
|
||||||
console.log(` Not WindowNostr: ${constructorName !== 'WindowNostr'}`);
|
// console.log(` Not WindowNostr: ${constructorName !== 'WindowNostr'}`);
|
||||||
console.log(` Not NostrLite: ${constructorName !== 'NostrLite'}`);
|
// console.log(` Not NostrLite: ${constructorName !== 'NostrLite'}`);
|
||||||
console.log(` Constructor: "${constructorName}"`);
|
// console.log(` Constructor: "${constructorName}"`);
|
||||||
|
|
||||||
// Additional debugging for comparison
|
// Additional debugging for comparison
|
||||||
const extensionPropChecks = {
|
const extensionPropChecks = {
|
||||||
@@ -868,7 +868,7 @@ class Modal {
|
|||||||
description: !!obj.description
|
description: !!obj.description
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log(`Modal: Extension property analysis:`, extensionPropChecks);
|
// console.log(`Modal: Extension property analysis:`, extensionPropChecks);
|
||||||
|
|
||||||
const hasExtensionProps = !!(
|
const hasExtensionProps = !!(
|
||||||
obj._isEnabled || obj.enabled || obj.kind ||
|
obj._isEnabled || obj.enabled || obj.kind ||
|
||||||
@@ -878,15 +878,15 @@ class Modal {
|
|||||||
|
|
||||||
const underscoreKeys = objectKeys.filter(key => key.startsWith('_'));
|
const underscoreKeys = objectKeys.filter(key => key.startsWith('_'));
|
||||||
const hexToUint8Keys = objectKeys.filter(key => key.startsWith('_hex'));
|
const hexToUint8Keys = objectKeys.filter(key => key.startsWith('_hex'));
|
||||||
console.log(`Modal: Underscore keys: [${underscoreKeys.join(', ')}]`);
|
// console.log(`Modal: Underscore keys: [${underscoreKeys.join(', ')}]`);
|
||||||
console.log(`Modal: _hex* keys: [${hexToUint8Keys.join(', ')}]`);
|
// console.log(`Modal: _hex* keys: [${hexToUint8Keys.join(', ')}]`);
|
||||||
|
|
||||||
console.log(`Modal: Additional analysis:`);
|
// console.log(`Modal: Additional analysis:`);
|
||||||
console.log(` hasExtensionProps: ${hasExtensionProps}`);
|
// console.log(` hasExtensionProps: ${hasExtensionProps}`);
|
||||||
console.log(` hasLibraryMethod (_hexToUint8Array): ${objectKeys.includes('_hexToUint8Array')}`);
|
// console.log(` hasLibraryMethod (_hexToUint8Array): ${objectKeys.includes('_hexToUint8Array')}`);
|
||||||
|
|
||||||
console.log(`Modal: COMPREHENSIVE TEST LOGIC RESULT: ${isRealExtension ? 'ACCEPT' : 'REJECT'}`);
|
// console.log(`Modal: COMPREHENSIVE TEST LOGIC RESULT: ${isRealExtension ? 'ACCEPT' : 'REJECT'}`);
|
||||||
console.log(`Modal: FINAL DECISION for ${constructorName}: ${isRealExtension ? 'ACCEPT' : 'REJECT'}`);
|
// console.log(`Modal: FINAL DECISION for ${constructorName}: ${isRealExtension ? 'ACCEPT' : 'REJECT'}`);
|
||||||
|
|
||||||
return isRealExtension;
|
return isRealExtension;
|
||||||
}
|
}
|
||||||
@@ -1140,7 +1140,7 @@ class Modal {
|
|||||||
textarea.oninput();
|
textarea.oninput();
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Generated new local secret key (nsec format)');
|
// console.log('Generated new local secret key (nsec format)');
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to generate local key:', error);
|
console.error('Failed to generate local key:', error);
|
||||||
@@ -1443,15 +1443,15 @@ class Modal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_setAuthMethod(method, options = {}) {
|
_setAuthMethod(method, options = {}) {
|
||||||
console.log('Modal: _setAuthMethod called with:', method, options);
|
// console.log('Modal: _setAuthMethod called with:', method, options);
|
||||||
|
|
||||||
// CRITICAL: Never install facade for extension methods - leave window.nostr as the extension
|
// CRITICAL: Never install facade for extension methods - leave window.nostr as the extension
|
||||||
if (method === 'extension') {
|
if (method === 'extension') {
|
||||||
console.log('Modal: Extension method - NOT installing facade, leaving window.nostr as extension');
|
// console.log('Modal: Extension method - NOT installing facade, leaving window.nostr as extension');
|
||||||
|
|
||||||
// Save extension authentication state using global setAuthState function
|
// Save extension authentication state using global setAuthState function
|
||||||
if (typeof window.setAuthState === 'function') {
|
if (typeof window.setAuthState === 'function') {
|
||||||
console.log('Modal: Saving extension auth state to storage');
|
// console.log('Modal: Saving extension auth state to storage');
|
||||||
window.setAuthState({ method, ...options }, { isolateSession: this.options?.isolateSession });
|
window.setAuthState({ method, ...options }, { isolateSession: this.options?.isolateSession });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1466,7 +1466,7 @@ class Modal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FOR NON-EXTENSION METHODS: Force-install facade with resilience
|
// FOR NON-EXTENSION METHODS: Force-install facade with resilience
|
||||||
console.log('Modal: Non-extension method - FORCE-INSTALLING facade with resilience:', method);
|
// console.log('Modal: Non-extension method - FORCE-INSTALLING facade with resilience:', method);
|
||||||
|
|
||||||
// Store the current extension if any (for potential restoration later)
|
// Store the current extension if any (for potential restoration later)
|
||||||
const currentExtension = (window.nostr?.constructor?.name !== 'WindowNostr') ? window.nostr : null;
|
const currentExtension = (window.nostr?.constructor?.name !== 'WindowNostr') ? window.nostr : null;
|
||||||
@@ -1485,10 +1485,10 @@ class Modal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IMMEDIATE FACADE INSTALLATION
|
// IMMEDIATE FACADE INSTALLATION
|
||||||
console.log('Modal: Installing WindowNostr facade immediately for method:', method);
|
// console.log('Modal: Installing WindowNostr facade immediately for method:', method);
|
||||||
const preservedExtension = nostrLiteInstance.preservedExtension || currentExtension;
|
const preservedExtension = nostrLiteInstance.preservedExtension || currentExtension;
|
||||||
nostrLiteInstance._installFacade(preservedExtension, true);
|
nostrLiteInstance._installFacade(preservedExtension, true);
|
||||||
console.log('Modal: WindowNostr facade force-installed, current window.nostr:', window.nostr?.constructor?.name);
|
// console.log('Modal: WindowNostr facade force-installed, current window.nostr:', window.nostr?.constructor?.name);
|
||||||
|
|
||||||
// DELAYED FACADE RESILIENCE - Reinstall after extension override attempts
|
// DELAYED FACADE RESILIENCE - Reinstall after extension override attempts
|
||||||
const forceReinstallFacade = () => {
|
const forceReinstallFacade = () => {
|
||||||
@@ -1513,9 +1513,9 @@ class Modal {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Schedule resilience checks at multiple intervals
|
// Schedule resilience checks at multiple intervals
|
||||||
setTimeout(forceReinstallFacade, 100); // Quick check
|
// setTimeout(forceReinstallFacade, 100); // Quick check
|
||||||
setTimeout(forceReinstallFacade, 500); // Main check
|
// setTimeout(forceReinstallFacade, 500); // Main check
|
||||||
setTimeout(forceReinstallFacade, 1500); // Final check
|
// setTimeout(forceReinstallFacade, 1500); // Final check
|
||||||
|
|
||||||
// Emit auth method selection
|
// Emit auth method selection
|
||||||
const event = new CustomEvent('nlMethodSelected', {
|
const event = new CustomEvent('nlMethodSelected', {
|
||||||
@@ -1702,7 +1702,7 @@ class Modal {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log('Bunker key validation failed:', error.message);
|
// console.log('Bunker key validation failed:', error.message);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1755,7 +1755,7 @@ class Modal {
|
|||||||
|
|
||||||
async _performNip46Connect(bunkerPubkey) {
|
async _performNip46Connect(bunkerPubkey) {
|
||||||
try {
|
try {
|
||||||
console.log('Starting NIP-46 connection to bunker:', bunkerPubkey);
|
// console.log('Starting NIP-46 connection to bunker:', bunkerPubkey);
|
||||||
|
|
||||||
// Check if nostr-tools NIP-46 is available
|
// Check if nostr-tools NIP-46 is available
|
||||||
if (!window.NostrTools?.nip46) {
|
if (!window.NostrTools?.nip46) {
|
||||||
@@ -1763,41 +1763,41 @@ class Modal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use nostr-tools to parse bunker input - this handles all formats correctly
|
// Use nostr-tools to parse bunker input - this handles all formats correctly
|
||||||
console.log('Parsing bunker input with nostr-tools...');
|
// console.log('Parsing bunker input with nostr-tools...');
|
||||||
const bunkerPointer = await window.NostrTools.nip46.parseBunkerInput(bunkerPubkey);
|
const bunkerPointer = await window.NostrTools.nip46.parseBunkerInput(bunkerPubkey);
|
||||||
|
|
||||||
if (!bunkerPointer) {
|
if (!bunkerPointer) {
|
||||||
throw new Error('Unable to parse bunker connection string or resolve NIP-05 identifier');
|
throw new Error('Unable to parse bunker connection string or resolve NIP-05 identifier');
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Parsed bunker pointer:', bunkerPointer);
|
// console.log('Parsed bunker pointer:', bunkerPointer);
|
||||||
|
|
||||||
// Create local client keypair for this session
|
// Create local client keypair for this session
|
||||||
const localSecretKey = window.NostrTools.generateSecretKey();
|
const localSecretKey = window.NostrTools.generateSecretKey();
|
||||||
console.log('Generated local client keypair for NIP-46 session');
|
// console.log('Generated local client keypair for NIP-46 session');
|
||||||
|
|
||||||
// Use nostr-tools BunkerSigner factory method (not constructor - it's private)
|
// Use nostr-tools BunkerSigner factory method (not constructor - it's private)
|
||||||
console.log('Creating nip46 BunkerSigner...');
|
// console.log('Creating nip46 BunkerSigner...');
|
||||||
const signer = window.NostrTools.nip46.BunkerSigner.fromBunker(localSecretKey, bunkerPointer, {
|
const signer = window.NostrTools.nip46.BunkerSigner.fromBunker(localSecretKey, bunkerPointer, {
|
||||||
onauth: (url) => {
|
onauth: (url) => {
|
||||||
console.log('Received auth URL from bunker:', url);
|
// console.log('Received auth URL from bunker:', url);
|
||||||
// Open auth URL in popup or redirect
|
// Open auth URL in popup or redirect
|
||||||
window.open(url, '_blank', 'width=600,height=800');
|
window.open(url, '_blank', 'width=600,height=800');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('NIP-46 BunkerSigner created successfully');
|
// console.log('NIP-46 BunkerSigner created successfully');
|
||||||
|
|
||||||
// Skip ping test - NIP-46 works through relays, not direct connection
|
// Skip ping test - NIP-46 works through relays, not direct connection
|
||||||
// Try to connect directly (this may trigger auth flow)
|
// Try to connect directly (this may trigger auth flow)
|
||||||
console.log('Attempting NIP-46 connect...');
|
// console.log('Attempting NIP-46 connect...');
|
||||||
await signer.connect();
|
await signer.connect();
|
||||||
console.log('NIP-46 connect successful');
|
// console.log('NIP-46 connect successful');
|
||||||
|
|
||||||
// Get the user's public key from the bunker
|
// Get the user's public key from the bunker
|
||||||
console.log('Getting public key from bunker...');
|
// console.log('Getting public key from bunker...');
|
||||||
const userPubkey = await signer.getPublicKey();
|
const userPubkey = await signer.getPublicKey();
|
||||||
console.log('NIP-46 user public key:', userPubkey);
|
// console.log('NIP-46 user public key:', userPubkey);
|
||||||
|
|
||||||
// Store the NIP-46 authentication info
|
// Store the NIP-46 authentication info
|
||||||
const nip46Info = {
|
const nip46Info = {
|
||||||
@@ -1811,7 +1811,7 @@ class Modal {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('NOSTR_LOGIN_LITE NIP-46 connection established successfully!');
|
// console.log('NOSTR_LOGIN_LITE NIP-46 connection established successfully!');
|
||||||
|
|
||||||
// Set as current auth method
|
// Set as current auth method
|
||||||
this._setAuthMethod('nip46', nip46Info);
|
this._setAuthMethod('nip46', nip46Info);
|
||||||
@@ -1984,7 +1984,7 @@ class Modal {
|
|||||||
textarea.oninput();
|
textarea.oninput();
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Generated new seed phrase:', mnemonic.split(/\s+/).length, 'words');
|
// console.log('Generated new seed phrase:', mnemonic.split(/\s+/).length, 'words');
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to generate seed phrase:', error);
|
console.error('Failed to generate seed phrase:', error);
|
||||||
@@ -2012,7 +2012,7 @@ class Modal {
|
|||||||
window.NostrTools.nip06.privateKeyFromSeedWords(mnemonic, '', 0);
|
window.NostrTools.nip06.privateKeyFromSeedWords(mnemonic, '', 0);
|
||||||
return true;
|
return true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log('Mnemonic validation failed:', error.message);
|
// console.log('Mnemonic validation failed:', error.message);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2054,7 +2054,7 @@ class Modal {
|
|||||||
throw new Error('Failed to derive any accounts from seed phrase');
|
throw new Error('Failed to derive any accounts from seed phrase');
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`Successfully derived ${accounts.length} accounts from seed phrase`);
|
// console.log(`Successfully derived ${accounts.length} accounts from seed phrase`);
|
||||||
this._showAccountSelection(accounts);
|
this._showAccountSelection(accounts);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -2150,7 +2150,7 @@ class Modal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_selectAccount(account) {
|
_selectAccount(account) {
|
||||||
console.log('Selected account:', account.index, account.npub);
|
// console.log('Selected account:', account.index, account.npub);
|
||||||
|
|
||||||
// Use the same auth method as local keys, but with seedphrase identifier
|
// Use the same auth method as local keys, but with seedphrase identifier
|
||||||
this._setAuthMethod('local', {
|
this._setAuthMethod('local', {
|
||||||
@@ -2898,7 +2898,7 @@ class NostrLite {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async init(options = {}) {
|
async init(options = {}) {
|
||||||
console.log('NOSTR_LOGIN_LITE: Initializing with options:', options);
|
// console.log('NOSTR_LOGIN_LITE: Initializing with options:', options);
|
||||||
|
|
||||||
this.options = {
|
this.options = {
|
||||||
theme: 'default',
|
theme: 'default',
|
||||||
@@ -2946,12 +2946,12 @@ class NostrLite {
|
|||||||
|
|
||||||
// Create modal during init (matching original git architecture)
|
// Create modal during init (matching original git architecture)
|
||||||
this.modal = new Modal(this.options);
|
this.modal = new Modal(this.options);
|
||||||
console.log('NOSTR_LOGIN_LITE: Modal created during init');
|
// console.log('NOSTR_LOGIN_LITE: Modal created during init');
|
||||||
|
|
||||||
// Initialize floating tab if enabled
|
// Initialize floating tab if enabled
|
||||||
if (this.options.floatingTab.enabled) {
|
if (this.options.floatingTab.enabled) {
|
||||||
this.floatingTab = new FloatingTab(this.modal, this.options.floatingTab);
|
this.floatingTab = new FloatingTab(this.modal, this.options.floatingTab);
|
||||||
console.log('NOSTR_LOGIN_LITE: Floating tab initialized');
|
// console.log('NOSTR_LOGIN_LITE: Floating tab initialized');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to restore authentication state if persistence is enabled (AFTER facade is ready)
|
// Attempt to restore authentication state if persistence is enabled (AFTER facade is ready)
|
||||||
@@ -2963,7 +2963,7 @@ class NostrLite {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.initialized = true;
|
this.initialized = true;
|
||||||
console.log('NOSTR_LOGIN_LITE: Initialization complete');
|
// console.log('NOSTR_LOGIN_LITE: Initialization complete');
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -3098,7 +3098,7 @@ class NostrLite {
|
|||||||
}
|
}
|
||||||
|
|
||||||
launch(startScreen = 'login') {
|
launch(startScreen = 'login') {
|
||||||
console.log('NOSTR_LOGIN_LITE: Launching with screen:', startScreen);
|
// console.log('NOSTR_LOGIN_LITE: Launching with screen:', startScreen);
|
||||||
|
|
||||||
if (this.modal) {
|
if (this.modal) {
|
||||||
this.modal.open({ startScreen });
|
this.modal.open({ startScreen });
|
||||||
@@ -3110,18 +3110,14 @@ class NostrLite {
|
|||||||
// Attempt to restore authentication state
|
// Attempt to restore authentication state
|
||||||
async _attemptAuthRestore() {
|
async _attemptAuthRestore() {
|
||||||
try {
|
try {
|
||||||
console.log('🔍 NOSTR_LOGIN_LITE: === _attemptAuthRestore START ===');
|
|
||||||
console.log('🔍 NOSTR_LOGIN_LITE: hasExtension:', this.hasExtension);
|
|
||||||
console.log('🔍 NOSTR_LOGIN_LITE: facadeInstalled:', this.facadeInstalled);
|
|
||||||
console.log('🔍 NOSTR_LOGIN_LITE: window.nostr:', window.nostr?.constructor?.name);
|
|
||||||
|
|
||||||
if (this.hasExtension) {
|
if (this.hasExtension) {
|
||||||
// EXTENSION MODE: Use custom extension persistence logic
|
// EXTENSION MODE: Use custom extension persistence logic
|
||||||
console.log('🔍 NOSTR_LOGIN_LITE: Extension mode - using extension-specific restore');
|
|
||||||
const restoredAuth = await this._attemptExtensionRestore();
|
const restoredAuth = await this._attemptExtensionRestore();
|
||||||
|
|
||||||
if (restoredAuth) {
|
if (restoredAuth) {
|
||||||
console.log('🔍 NOSTR_LOGIN_LITE: ✅ Extension auth restored successfully!');
|
|
||||||
return restoredAuth;
|
return restoredAuth;
|
||||||
} else {
|
} else {
|
||||||
console.log('🔍 NOSTR_LOGIN_LITE: ❌ Extension auth could not be restored');
|
console.log('🔍 NOSTR_LOGIN_LITE: ❌ Extension auth could not be restored');
|
||||||
@@ -3133,14 +3129,11 @@ class NostrLite {
|
|||||||
const restoredAuth = await window.nostr.restoreAuthState();
|
const restoredAuth = await window.nostr.restoreAuthState();
|
||||||
|
|
||||||
if (restoredAuth) {
|
if (restoredAuth) {
|
||||||
console.log('🔍 NOSTR_LOGIN_LITE: ✅ Facade auth restored successfully!');
|
|
||||||
console.log('🔍 NOSTR_LOGIN_LITE: Method:', restoredAuth.method);
|
|
||||||
console.log('🔍 NOSTR_LOGIN_LITE: Pubkey:', restoredAuth.pubkey);
|
|
||||||
|
|
||||||
// CRITICAL FIX: Activate facade resilience system for non-extension methods
|
// CRITICAL FIX: Activate facade resilience system for non-extension methods
|
||||||
// Extensions like nos2x can override our facade after page refresh
|
// Extensions like nos2x can override our facade after page refresh
|
||||||
if (restoredAuth.method === 'local' || restoredAuth.method === 'nip46') {
|
if (restoredAuth.method === 'local' || restoredAuth.method === 'nip46') {
|
||||||
console.log('🔍 NOSTR_LOGIN_LITE: 🛡️ Activating facade resilience system for page refresh');
|
|
||||||
this._activateResilienceProtection(restoredAuth.method);
|
this._activateResilienceProtection(restoredAuth.method);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3272,7 +3265,7 @@ class NostrLite {
|
|||||||
|
|
||||||
// Show prompt for NIP-46 reconnection
|
// Show prompt for NIP-46 reconnection
|
||||||
_showReconnectionPrompt(authData) {
|
_showReconnectionPrompt(authData) {
|
||||||
console.log('NOSTR_LOGIN_LITE: Showing reconnection prompt for NIP-46');
|
|
||||||
|
|
||||||
// Dispatch event that UI can listen to
|
// Dispatch event that UI can listen to
|
||||||
if (typeof window !== 'undefined') {
|
if (typeof window !== 'undefined') {
|
||||||
@@ -3404,10 +3397,10 @@ class AuthManager {
|
|||||||
// Configure storage type based on isolateSession option
|
// Configure storage type based on isolateSession option
|
||||||
if (options.isolateSession) {
|
if (options.isolateSession) {
|
||||||
this.storage = sessionStorage;
|
this.storage = sessionStorage;
|
||||||
console.log('🔐 AuthManager: Using sessionStorage for per-window isolation');
|
// console.log('🔐 AuthManager: Using sessionStorage for per-window isolation');
|
||||||
} else {
|
} else {
|
||||||
this.storage = localStorage;
|
this.storage = localStorage;
|
||||||
console.log('🔐 AuthManager: Using localStorage for cross-window persistence');
|
// console.log('🔐 AuthManager: Using localStorage for cross-window persistence');
|
||||||
}
|
}
|
||||||
|
|
||||||
console.warn('🔐 SECURITY: Private keys stored unencrypted in browser storage');
|
console.warn('🔐 SECURITY: Private keys stored unencrypted in browser storage');
|
||||||
@@ -3417,8 +3410,7 @@ class AuthManager {
|
|||||||
// Save authentication state using unified plaintext approach
|
// Save authentication state using unified plaintext approach
|
||||||
async saveAuthState(authData) {
|
async saveAuthState(authData) {
|
||||||
try {
|
try {
|
||||||
console.log('🔐 AuthManager: Saving auth state with plaintext storage');
|
|
||||||
console.warn('🔐 SECURITY: Private key will be stored unencrypted for maximum usability');
|
|
||||||
|
|
||||||
const authState = {
|
const authState = {
|
||||||
method: authData.method,
|
method: authData.method,
|
||||||
@@ -3434,15 +3426,14 @@ class AuthManager {
|
|||||||
hasGetPublicKey: typeof authData.extension?.getPublicKey === 'function',
|
hasGetPublicKey: typeof authData.extension?.getPublicKey === 'function',
|
||||||
hasSignEvent: typeof authData.extension?.signEvent === 'function'
|
hasSignEvent: typeof authData.extension?.signEvent === 'function'
|
||||||
};
|
};
|
||||||
console.log('🔐 AuthManager: Extension method - storing verification data only');
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'local':
|
case 'local':
|
||||||
// UNIFIED PLAINTEXT: Store secret key directly for maximum compatibility
|
// UNIFIED PLAINTEXT: Store secret key directly for maximum compatibility
|
||||||
if (authData.secret) {
|
if (authData.secret) {
|
||||||
authState.secret = authData.secret;
|
authState.secret = authData.secret;
|
||||||
console.log('🔐 AuthManager: Local method - storing secret key in plaintext');
|
|
||||||
console.warn('🔐 SECURITY: Secret key stored unencrypted for developer convenience');
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -3454,13 +3445,13 @@ class AuthManager {
|
|||||||
relays: authData.signer.relays,
|
relays: authData.signer.relays,
|
||||||
// Don't store secret - user will need to reconnect
|
// Don't store secret - user will need to reconnect
|
||||||
};
|
};
|
||||||
console.log('🔐 AuthManager: NIP-46 method - storing connection parameters');
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'readonly':
|
case 'readonly':
|
||||||
// Read-only mode has no secrets to store
|
// Read-only mode has no secrets to store
|
||||||
console.log('🔐 AuthManager: Read-only method - storing basic auth state');
|
// console.log('🔐 AuthManager: Read-only method - storing basic auth state');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -3469,7 +3460,7 @@ class AuthManager {
|
|||||||
|
|
||||||
this.storage.setItem(this.storageKey, JSON.stringify(authState));
|
this.storage.setItem(this.storageKey, JSON.stringify(authState));
|
||||||
this.currentAuthState = authState;
|
this.currentAuthState = authState;
|
||||||
console.log('🔐 AuthManager: Auth state saved successfully for method:', authData.method);
|
// console.log('🔐 AuthManager: Auth state saved successfully for method:', authData.method);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('🔐 AuthManager: Failed to save auth state:', error);
|
console.error('🔐 AuthManager: Failed to save auth state:', error);
|
||||||
@@ -3480,11 +3471,10 @@ class AuthManager {
|
|||||||
// Restore authentication state on page load
|
// Restore authentication state on page load
|
||||||
async restoreAuthState() {
|
async restoreAuthState() {
|
||||||
try {
|
try {
|
||||||
console.log('🔍 AuthManager: === restoreAuthState START ===');
|
|
||||||
console.log('🔍 AuthManager: storageKey:', this.storageKey);
|
|
||||||
|
|
||||||
const stored = this.storage.getItem(this.storageKey);
|
const stored = this.storage.getItem(this.storageKey);
|
||||||
console.log('🔍 AuthManager: Storage raw value:', stored);
|
|
||||||
|
|
||||||
if (!stored) {
|
if (!stored) {
|
||||||
console.log('🔍 AuthManager: ❌ No stored auth state found');
|
console.log('🔍 AuthManager: ❌ No stored auth state found');
|
||||||
@@ -3492,10 +3482,7 @@ class AuthManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const authState = JSON.parse(stored);
|
const authState = JSON.parse(stored);
|
||||||
console.log('🔍 AuthManager: ✅ Parsed stored auth state:', authState);
|
|
||||||
console.log('🔍 AuthManager: Method:', authState.method);
|
|
||||||
console.log('🔍 AuthManager: Timestamp:', authState.timestamp);
|
|
||||||
console.log('🔍 AuthManager: Age (ms):', Date.now() - authState.timestamp);
|
|
||||||
|
|
||||||
// Check if stored state is too old (24 hours for most methods, 1 hour for extensions)
|
// Check if stored state is too old (24 hours for most methods, 1 hour for extensions)
|
||||||
const maxAge = authState.method === 'extension' ? 60 * 60 * 1000 : 24 * 60 * 60 * 1000;
|
const maxAge = authState.method === 'extension' ? 60 * 60 * 1000 : 24 * 60 * 60 * 1000;
|
||||||
@@ -3507,27 +3494,26 @@ class AuthManager {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('🔍 AuthManager: ✅ Auth state not expired, attempting restore for method:', authState.method);
|
|
||||||
|
|
||||||
let result;
|
let result;
|
||||||
switch (authState.method) {
|
switch (authState.method) {
|
||||||
case 'extension':
|
case 'extension':
|
||||||
console.log('🔍 AuthManager: Calling _restoreExtensionAuth...');
|
|
||||||
result = await this._restoreExtensionAuth(authState);
|
result = await this._restoreExtensionAuth(authState);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'local':
|
case 'local':
|
||||||
console.log('🔍 AuthManager: Calling _restoreLocalAuth...');
|
|
||||||
result = await this._restoreLocalAuth(authState);
|
result = await this._restoreLocalAuth(authState);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'nip46':
|
case 'nip46':
|
||||||
console.log('🔍 AuthManager: Calling _restoreNip46Auth...');
|
|
||||||
result = await this._restoreNip46Auth(authState);
|
result = await this._restoreNip46Auth(authState);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'readonly':
|
case 'readonly':
|
||||||
console.log('🔍 AuthManager: Calling _restoreReadonlyAuth...');
|
|
||||||
result = await this._restoreReadonlyAuth(authState);
|
result = await this._restoreReadonlyAuth(authState);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -3536,8 +3522,6 @@ class AuthManager {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('🔍 AuthManager: Restore method result:', result);
|
|
||||||
console.log('🔍 AuthManager: === restoreAuthState END ===');
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -3563,19 +3547,14 @@ class AuthManager {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('🔍 AuthManager: ✅ Extension found:', extension.constructor?.name);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Verify extension still works and has same pubkey
|
// Verify extension still works and has same pubkey
|
||||||
const currentPubkey = await extension.getPublicKey();
|
const currentPubkey = await extension.getPublicKey();
|
||||||
if (currentPubkey !== authState.pubkey) {
|
|
||||||
console.log('🔍 AuthManager: ❌ Extension pubkey changed, not restoring');
|
|
||||||
console.log('🔍 AuthManager: Expected:', authState.pubkey);
|
|
||||||
console.log('🔍 AuthManager: Got:', currentPubkey);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('🔍 AuthManager: ✅ Extension auth restored successfully');
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
method: 'extension',
|
method: 'extension',
|
||||||
pubkey: authState.pubkey,
|
pubkey: authState.pubkey,
|
||||||
@@ -3583,16 +3562,14 @@ class AuthManager {
|
|||||||
};
|
};
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log('🔍 AuthManager: ❌ Extension verification failed:', error);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Smart extension waiting system - polls multiple locations for extensions
|
// Smart extension waiting system - polls multiple locations for extensions
|
||||||
async _waitForExtension(authState, maxWaitMs = 3000) {
|
async _waitForExtension(authState, maxWaitMs = 3000) {
|
||||||
console.log('🔍 AuthManager: === _waitForExtension START ===');
|
|
||||||
console.log('🔍 AuthManager: maxWaitMs:', maxWaitMs);
|
|
||||||
console.log('🔍 AuthManager: Looking for extension with constructor:', authState.extensionVerification?.constructor);
|
|
||||||
|
|
||||||
const startTime = Date.now();
|
const startTime = Date.now();
|
||||||
const pollInterval = 100; // Check every 100ms
|
const pollInterval = 100; // Check every 100ms
|
||||||
@@ -3610,13 +3587,13 @@ class AuthManager {
|
|||||||
];
|
];
|
||||||
|
|
||||||
while (Date.now() - startTime < maxWaitMs) {
|
while (Date.now() - startTime < maxWaitMs) {
|
||||||
console.log('🔍 AuthManager: Polling for extensions... (elapsed:', Date.now() - startTime, 'ms)');
|
|
||||||
|
|
||||||
// If our facade is currently installed and blocking, temporarily remove it
|
// If our facade is currently installed and blocking, temporarily remove it
|
||||||
let facadeRemoved = false;
|
let facadeRemoved = false;
|
||||||
let originalNostr = null;
|
let originalNostr = null;
|
||||||
if (window.nostr?.constructor?.name === 'WindowNostr') {
|
if (window.nostr?.constructor?.name === 'WindowNostr') {
|
||||||
console.log('🔍 AuthManager: Temporarily removing our facade to check for real extensions');
|
|
||||||
originalNostr = window.nostr;
|
originalNostr = window.nostr;
|
||||||
window.nostr = window.nostr.existingNostr || undefined;
|
window.nostr = window.nostr.existingNostr || undefined;
|
||||||
facadeRemoved = true;
|
facadeRemoved = true;
|
||||||
@@ -3627,21 +3604,21 @@ class AuthManager {
|
|||||||
for (const location of extensionLocations) {
|
for (const location of extensionLocations) {
|
||||||
try {
|
try {
|
||||||
const extension = location.getter();
|
const extension = location.getter();
|
||||||
console.log('🔍 AuthManager: Checking', location.path, ':', !!extension, extension?.constructor?.name);
|
|
||||||
|
|
||||||
if (this._isValidExtensionForRestore(extension, authState)) {
|
if (this._isValidExtensionForRestore(extension, authState)) {
|
||||||
console.log('🔍 AuthManager: ✅ Found matching extension at', location.path);
|
|
||||||
|
|
||||||
// Restore facade if we removed it
|
// Restore facade if we removed it
|
||||||
if (facadeRemoved && originalNostr) {
|
if (facadeRemoved && originalNostr) {
|
||||||
console.log('🔍 AuthManager: Restoring facade after finding extension');
|
|
||||||
window.nostr = originalNostr;
|
window.nostr = originalNostr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return extension;
|
return extension;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log('🔍 AuthManager: Error checking', location.path, ':', error.message);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3702,31 +3679,27 @@ class AuthManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('🔍 AuthManager: ✅ Extension validation passed for:', constructorName);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async _restoreLocalAuth(authState) {
|
async _restoreLocalAuth(authState) {
|
||||||
console.log('🔐 AuthManager: === _restoreLocalAuth (Unified Plaintext) ===');
|
|
||||||
|
|
||||||
// Check for legacy encrypted format first
|
|
||||||
if (authState.encrypted) {
|
if (authState.encrypted) {
|
||||||
console.log('🔐 AuthManager: Detected LEGACY encrypted format - migrating to plaintext');
|
|
||||||
console.warn('🔐 SECURITY: Converting from encrypted to plaintext storage for compatibility');
|
|
||||||
|
|
||||||
// Try to decrypt legacy format
|
// Try to decrypt legacy format
|
||||||
const sessionPassword = sessionStorage.getItem('nostr_session_key');
|
const sessionPassword = sessionStorage.getItem('nostr_session_key');
|
||||||
if (!sessionPassword) {
|
if (!sessionPassword) {
|
||||||
console.log('🔐 AuthManager: Legacy session password not found - user must re-login');
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.warn('🔐 AuthManager: Legacy encryption system no longer supported - user must re-login');
|
|
||||||
this.clearAuthState(); // Clear legacy format
|
this.clearAuthState(); // Clear legacy format
|
||||||
return null;
|
return null;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('🔐 AuthManager: Legacy decryption failed:', error);
|
|
||||||
this.clearAuthState(); // Clear corrupted legacy format
|
this.clearAuthState(); // Clear corrupted legacy format
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -3734,12 +3707,11 @@ class AuthManager {
|
|||||||
|
|
||||||
// NEW UNIFIED PLAINTEXT FORMAT
|
// NEW UNIFIED PLAINTEXT FORMAT
|
||||||
if (!authState.secret) {
|
if (!authState.secret) {
|
||||||
console.log('🔐 AuthManager: No secret found in plaintext format');
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('🔐 AuthManager: ✅ Local auth restored from plaintext storage');
|
|
||||||
console.warn('🔐 SECURITY: Secret key was stored unencrypted');
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
method: 'local',
|
method: 'local',
|
||||||
@@ -3750,14 +3722,14 @@ class AuthManager {
|
|||||||
|
|
||||||
async _restoreNip46Auth(authState) {
|
async _restoreNip46Auth(authState) {
|
||||||
if (!authState.nip46) {
|
if (!authState.nip46) {
|
||||||
console.log('🔐 AuthManager: No NIP-46 data found');
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For NIP-46, we can't automatically restore the connection
|
// For NIP-46, we can't automatically restore the connection
|
||||||
// because it requires the user to re-authenticate with the remote signer
|
// because it requires the user to re-authenticate with the remote signer
|
||||||
// Instead, we return the connection parameters so the UI can prompt for reconnection
|
// Instead, we return the connection parameters so the UI can prompt for reconnection
|
||||||
console.log('🔐 AuthManager: NIP-46 connection data found, requires user reconnection');
|
|
||||||
return {
|
return {
|
||||||
method: 'nip46',
|
method: 'nip46',
|
||||||
pubkey: authState.pubkey,
|
pubkey: authState.pubkey,
|
||||||
@@ -3767,7 +3739,7 @@ class AuthManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async _restoreReadonlyAuth(authState) {
|
async _restoreReadonlyAuth(authState) {
|
||||||
console.log('🔐 AuthManager: Read-only auth restored successfully');
|
|
||||||
return {
|
return {
|
||||||
method: 'readonly',
|
method: 'readonly',
|
||||||
pubkey: authState.pubkey
|
pubkey: authState.pubkey
|
||||||
@@ -3779,7 +3751,7 @@ class AuthManager {
|
|||||||
this.storage.removeItem(this.storageKey);
|
this.storage.removeItem(this.storageKey);
|
||||||
sessionStorage.removeItem('nostr_session_key'); // Clear legacy session key
|
sessionStorage.removeItem('nostr_session_key'); // Clear legacy session key
|
||||||
this.currentAuthState = null;
|
this.currentAuthState = null;
|
||||||
console.log('🔐 AuthManager: Auth state cleared from unified storage');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we have valid stored auth
|
// Check if we have valid stored auth
|
||||||
@@ -3822,8 +3794,8 @@ function getGlobalAuthManager() {
|
|||||||
// **UNIFIED GLOBAL FUNCTION**: Set authentication state (works for all methods)
|
// **UNIFIED GLOBAL FUNCTION**: Set authentication state (works for all methods)
|
||||||
function setAuthState(authData, options = {}) {
|
function setAuthState(authData, options = {}) {
|
||||||
try {
|
try {
|
||||||
console.log('🌐 setAuthState: Setting global auth state for method:', authData.method);
|
|
||||||
console.warn('🔐 SECURITY: Using unified plaintext storage for maximum compatibility');
|
|
||||||
|
|
||||||
// Store in memory
|
// Store in memory
|
||||||
globalAuthState = authData;
|
globalAuthState = authData;
|
||||||
@@ -3832,7 +3804,7 @@ function setAuthState(authData, options = {}) {
|
|||||||
const authManager = new AuthManager(options);
|
const authManager = new AuthManager(options);
|
||||||
authManager.saveAuthState(authData);
|
authManager.saveAuthState(authData);
|
||||||
|
|
||||||
console.log('🌐 setAuthState: Auth state saved successfully');
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('🌐 setAuthState: Failed to save auth state:', error);
|
console.error('🌐 setAuthState: Failed to save auth state:', error);
|
||||||
throw error;
|
throw error;
|
||||||
@@ -3855,13 +3827,13 @@ function getAuthState() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!stored) {
|
if (!stored) {
|
||||||
console.log('🌐 getAuthState: No auth state found in storage');
|
// console.log('🌐 getAuthState: No auth state found in storage');
|
||||||
globalAuthState = null;
|
globalAuthState = null;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const authState = JSON.parse(stored);
|
const authState = JSON.parse(stored);
|
||||||
console.log('🌐 getAuthState: Retrieved auth state:', authState.method);
|
// console.log('🌐 getAuthState: Retrieved auth state:', authState.method);
|
||||||
|
|
||||||
// Update in-memory cache
|
// Update in-memory cache
|
||||||
globalAuthState = authState;
|
globalAuthState = authState;
|
||||||
@@ -3877,7 +3849,7 @@ function getAuthState() {
|
|||||||
// **UNIFIED GLOBAL FUNCTION**: Clear authentication state (works for all methods)
|
// **UNIFIED GLOBAL FUNCTION**: Clear authentication state (works for all methods)
|
||||||
function clearAuthState() {
|
function clearAuthState() {
|
||||||
try {
|
try {
|
||||||
console.log('🌐 clearAuthState: Clearing global auth state');
|
// console.log('🌐 clearAuthState: Clearing global auth state');
|
||||||
|
|
||||||
// Clear in-memory state
|
// Clear in-memory state
|
||||||
globalAuthState = null;
|
globalAuthState = null;
|
||||||
@@ -3888,7 +3860,7 @@ function clearAuthState() {
|
|||||||
sessionStorage.removeItem(storageKey);
|
sessionStorage.removeItem(storageKey);
|
||||||
sessionStorage.removeItem('nostr_session_key'); // Clear legacy session key
|
sessionStorage.removeItem('nostr_session_key'); // Clear legacy session key
|
||||||
|
|
||||||
console.log('🌐 clearAuthState: Auth state cleared from all storage locations');
|
// console.log('🌐 clearAuthState: Auth state cleared from all storage locations');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('🌐 clearAuthState: Failed to clear auth state:', error);
|
console.error('🌐 clearAuthState: Failed to clear auth state:', error);
|
||||||
}
|
}
|
||||||
@@ -4271,9 +4243,9 @@ if (typeof window !== 'undefined') {
|
|||||||
_instance: nostrLite
|
_instance: nostrLite
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('NOSTR_LOGIN_LITE: Library loaded and ready');
|
// console.log('NOSTR_LOGIN_LITE: Library loaded and ready');
|
||||||
console.log('NOSTR_LOGIN_LITE: Use window.NOSTR_LOGIN_LITE.init(options) to initialize');
|
// console.log('NOSTR_LOGIN_LITE: Use window.NOSTR_LOGIN_LITE.init(options) to initialize');
|
||||||
console.log('NOSTR_LOGIN_LITE: Detected', nostrLite.extensionBridge.getExtensionCount(), 'browser extensions');
|
// console.log('NOSTR_LOGIN_LITE: Detected', nostrLite.extensionBridge.getExtensionCount(), 'browser extensions');
|
||||||
console.warn('🔐 SECURITY: Unified plaintext storage enabled for maximum developer usability');
|
console.warn('🔐 SECURITY: Unified plaintext storage enabled for maximum developer usability');
|
||||||
} else {
|
} else {
|
||||||
// Node.js environment
|
// Node.js environment
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
rsync -avz --chmod=644 --progress lite/{nostr-lite.js,nostr.bundle.js} ubuntu@laantungir.net:WWW/nostr-login-lite/
|
rsync -avz --chmod=644 --progress build/{nostr-lite.js,nostr.bundle.js} ubuntu@laantungir.net:html/nostr-login-lite/
|
||||||
|
|||||||
@@ -35,6 +35,15 @@
|
|||||||
<!-- Load NOSTR_LOGIN_LITE main library (now includes NIP-46 extension) -->
|
<!-- Load NOSTR_LOGIN_LITE main library (now includes NIP-46 extension) -->
|
||||||
<script src="../lite/nostr-lite.js"></script>
|
<script src="../lite/nostr-lite.js"></script>
|
||||||
|
|
||||||
|
<!-- Load the official nostr-tools bundle first -->
|
||||||
|
<!-- <script src="./nostr.bundle.js"></script> -->
|
||||||
|
<script src="https://laantungir.net/nostr-login-lite/nostr.bundle.js"></script>
|
||||||
|
|
||||||
|
<!-- Load NOSTR_LOGIN_LITE main library -->
|
||||||
|
<script src="https://laantungir.net/nostr-login-lite/nostr-lite.js"></script>
|
||||||
|
<!-- <script src="./nostr-lite.js"></script> -->
|
||||||
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -55,14 +55,14 @@ new_tag="v$new_version"
|
|||||||
|
|
||||||
echo -e "${GREEN}📈 Incrementing version: $current_version → $new_version${NC}"
|
echo -e "${GREEN}📈 Incrementing version: $current_version → $new_version${NC}"
|
||||||
|
|
||||||
# Step 2.5: Save version to lite/VERSION file
|
# Step 2.5: Save version to src/VERSION file
|
||||||
echo -e "${YELLOW}💾 Saving version to lite/VERSION...${NC}"
|
echo -e "${YELLOW}💾 Saving version to src/VERSION...${NC}"
|
||||||
echo "$new_version" > lite/VERSION
|
echo "$new_version" > src/VERSION
|
||||||
echo -e "Version saved: ${GREEN}$new_version${NC}"
|
echo -e "Version saved: ${GREEN}$new_version${NC}"
|
||||||
|
|
||||||
# Step 2.5: Run build.js
|
# Step 2.5: Run build.js
|
||||||
echo -e "${YELLOW}🔧 Running build process...${NC}"
|
echo -e "${YELLOW}🔧 Running build process...${NC}"
|
||||||
cd lite
|
cd src
|
||||||
node build.js
|
node build.js
|
||||||
cd ..
|
cd ..
|
||||||
echo -e "${GREEN}✅ Build completed${NC}"
|
echo -e "${GREEN}✅ Build completed${NC}"
|
||||||
@@ -100,8 +100,8 @@ git push --tags
|
|||||||
|
|
||||||
echo -e "${GREEN}🎉 Successfully completed:${NC}"
|
echo -e "${GREEN}🎉 Successfully completed:${NC}"
|
||||||
echo -e " • Version incremented to: ${GREEN}$new_version${NC}"
|
echo -e " • Version incremented to: ${GREEN}$new_version${NC}"
|
||||||
echo -e " • VERSION file updated: ${GREEN}lite/VERSION${NC}"
|
echo -e " • VERSION file updated: ${GREEN}src/VERSION${NC}"
|
||||||
echo -e " • Build completed: ${GREEN}lite/nostr-lite.js${NC}"
|
echo -e " • Build completed: ${GREEN}build/nostr-lite.js${NC}"
|
||||||
echo -e " • Git tag created: ${GREEN}$new_tag${NC}"
|
echo -e " • Git tag created: ${GREEN}$new_tag${NC}"
|
||||||
echo -e " • Changes pushed to remote${NC}"
|
echo -e " • Changes pushed to remote${NC}"
|
||||||
echo -e "\n${GREEN}✨ Process complete!${NC}"
|
echo -e "\n${GREEN}✨ Process complete!${NC}"
|
||||||
@@ -1 +0,0 @@
|
|||||||
0.1.6
|
|
||||||
10
nostr_login_lite.code-workspace
Normal file
10
nostr_login_lite.code-workspace
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"folders": [
|
||||||
|
{
|
||||||
|
"path": "."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"settings": {
|
||||||
|
"liveServer.settings.port": 5501
|
||||||
|
}
|
||||||
|
}
|
||||||
1
src/VERSION
Normal file
1
src/VERSION
Normal file
@@ -0,0 +1 @@
|
|||||||
|
0.1.12
|
||||||
@@ -22,9 +22,9 @@ const fs = require('fs');
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
function createNostrLoginLiteBundle() {
|
function createNostrLoginLiteBundle() {
|
||||||
console.log('🔧 Creating NOSTR_LOGIN_LITE bundle for two-file architecture...');
|
// console.log('🔧 Creating NOSTR_LOGIN_LITE bundle for two-file architecture...');
|
||||||
|
|
||||||
const outputPath = path.join(__dirname, 'nostr-lite.js');
|
const outputPath = path.join(__dirname, '../build/nostr-lite.js');
|
||||||
|
|
||||||
// Remove old bundle
|
// Remove old bundle
|
||||||
try {
|
try {
|
||||||
@@ -56,10 +56,10 @@ if (typeof window !== 'undefined') {
|
|||||||
throw new Error('Missing dependency: nostr.bundle.js');
|
throw new Error('Missing dependency: nostr.bundle.js');
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('NOSTR_LOGIN_LITE: Dependencies verified ✓');
|
// console.log('NOSTR_LOGIN_LITE: Dependencies verified ✓');
|
||||||
console.log('NOSTR_LOGIN_LITE: NostrTools available with keys:', Object.keys(window.NostrTools));
|
// console.log('NOSTR_LOGIN_LITE: NostrTools available with keys:', Object.keys(window.NostrTools));
|
||||||
console.log('NOSTR_LOGIN_LITE: NIP-06 available:', !!window.NostrTools.nip06);
|
// console.log('NOSTR_LOGIN_LITE: NIP-06 available:', !!window.NostrTools.nip06);
|
||||||
console.log('NOSTR_LOGIN_LITE: NIP-46 available:', !!window.NostrTools.nip46);
|
// console.log('NOSTR_LOGIN_LITE: NIP-46 available:', !!window.NostrTools.nip46);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ======================================
|
// ======================================
|
||||||
@@ -69,7 +69,7 @@ if (typeof window !== 'undefined') {
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
// Embed CSS themes
|
// Embed CSS themes
|
||||||
console.log('🎨 Adding CSS-Only Theme System...');
|
// console.log('🎨 Adding CSS-Only Theme System...');
|
||||||
|
|
||||||
const defaultThemeCssPath = path.join(__dirname, '../themes/default/theme.css');
|
const defaultThemeCssPath = path.join(__dirname, '../themes/default/theme.css');
|
||||||
const darkThemeCssPath = path.join(__dirname, '../themes/dark/theme.css');
|
const darkThemeCssPath = path.join(__dirname, '../themes/dark/theme.css');
|
||||||
@@ -109,7 +109,7 @@ if (typeof window !== 'undefined') {
|
|||||||
bundle += ` style.id = 'nl-theme-css';\n`;
|
bundle += ` style.id = 'nl-theme-css';\n`;
|
||||||
bundle += ` style.textContent = themeCss;\n`;
|
bundle += ` style.textContent = themeCss;\n`;
|
||||||
bundle += ` document.head.appendChild(style);\n`;
|
bundle += ` document.head.appendChild(style);\n`;
|
||||||
bundle += ` console.log('NOSTR_LOGIN_LITE: ' + themeName + ' theme CSS injected');\n`;
|
bundle += ` // console.log('NOSTR_LOGIN_LITE: ' + themeName + ' theme CSS injected');\n`;
|
||||||
bundle += ` }\n`;
|
bundle += ` }\n`;
|
||||||
bundle += `}\n\n`;
|
bundle += `}\n\n`;
|
||||||
|
|
||||||
@@ -127,7 +127,7 @@ if (typeof window !== 'undefined') {
|
|||||||
// Add Modal UI
|
// Add Modal UI
|
||||||
const modalPath = path.join(__dirname, 'ui/modal.js');
|
const modalPath = path.join(__dirname, 'ui/modal.js');
|
||||||
if (fs.existsSync(modalPath)) {
|
if (fs.existsSync(modalPath)) {
|
||||||
console.log('📄 Adding Modal UI...');
|
// console.log('📄 Adding Modal UI...');
|
||||||
|
|
||||||
let modalContent = fs.readFileSync(modalPath, 'utf8');
|
let modalContent = fs.readFileSync(modalPath, 'utf8');
|
||||||
|
|
||||||
@@ -139,12 +139,12 @@ if (typeof window !== 'undefined') {
|
|||||||
try {
|
try {
|
||||||
const version = fs.readFileSync(versionPath, 'utf8').trim();
|
const version = fs.readFileSync(versionPath, 'utf8').trim();
|
||||||
versionString = 'v' + version;
|
versionString = 'v' + version;
|
||||||
console.log('🔢 Using version: ' + version);
|
// console.log('🔢 Using version: ' + version);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn('⚠️ Could not read VERSION file, no version will be displayed');
|
console.warn('⚠️ Could not read VERSION file, no version will be displayed');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log('📋 No VERSION file found, no version will be displayed');
|
// console.log('📋 No VERSION file found, no version will be displayed');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep modal title as just "Nostr Login" (no version injection)
|
// Keep modal title as just "Nostr Login" (no version injection)
|
||||||
@@ -200,7 +200,7 @@ if (typeof window !== 'undefined') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add main library code
|
// Add main library code
|
||||||
console.log('📄 Adding Main Library...');
|
// console.log('📄 Adding Main Library...');
|
||||||
bundle += `
|
bundle += `
|
||||||
// ======================================
|
// ======================================
|
||||||
// FloatingTab Component (Recovered from git history)
|
// FloatingTab Component (Recovered from git history)
|
||||||
@@ -887,7 +887,7 @@ class NostrLite {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async init(options = {}) {
|
async init(options = {}) {
|
||||||
console.log('NOSTR_LOGIN_LITE: Initializing with options:', options);
|
// console.log('NOSTR_LOGIN_LITE: Initializing with options:', options);
|
||||||
|
|
||||||
this.options = {
|
this.options = {
|
||||||
theme: 'default',
|
theme: 'default',
|
||||||
@@ -935,12 +935,12 @@ class NostrLite {
|
|||||||
|
|
||||||
// Create modal during init (matching original git architecture)
|
// Create modal during init (matching original git architecture)
|
||||||
this.modal = new Modal(this.options);
|
this.modal = new Modal(this.options);
|
||||||
console.log('NOSTR_LOGIN_LITE: Modal created during init');
|
// console.log('NOSTR_LOGIN_LITE: Modal created during init');
|
||||||
|
|
||||||
// Initialize floating tab if enabled
|
// Initialize floating tab if enabled
|
||||||
if (this.options.floatingTab.enabled) {
|
if (this.options.floatingTab.enabled) {
|
||||||
this.floatingTab = new FloatingTab(this.modal, this.options.floatingTab);
|
this.floatingTab = new FloatingTab(this.modal, this.options.floatingTab);
|
||||||
console.log('NOSTR_LOGIN_LITE: Floating tab initialized');
|
// console.log('NOSTR_LOGIN_LITE: Floating tab initialized');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to restore authentication state if persistence is enabled (AFTER facade is ready)
|
// Attempt to restore authentication state if persistence is enabled (AFTER facade is ready)
|
||||||
@@ -952,7 +952,7 @@ class NostrLite {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.initialized = true;
|
this.initialized = true;
|
||||||
console.log('NOSTR_LOGIN_LITE: Initialization complete');
|
// console.log('NOSTR_LOGIN_LITE: Initialization complete');
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -1087,7 +1087,7 @@ class NostrLite {
|
|||||||
}
|
}
|
||||||
|
|
||||||
launch(startScreen = 'login') {
|
launch(startScreen = 'login') {
|
||||||
console.log('NOSTR_LOGIN_LITE: Launching with screen:', startScreen);
|
// console.log('NOSTR_LOGIN_LITE: Launching with screen:', startScreen);
|
||||||
|
|
||||||
if (this.modal) {
|
if (this.modal) {
|
||||||
this.modal.open({ startScreen });
|
this.modal.open({ startScreen });
|
||||||
@@ -1099,18 +1099,14 @@ class NostrLite {
|
|||||||
// Attempt to restore authentication state
|
// Attempt to restore authentication state
|
||||||
async _attemptAuthRestore() {
|
async _attemptAuthRestore() {
|
||||||
try {
|
try {
|
||||||
console.log('🔍 NOSTR_LOGIN_LITE: === _attemptAuthRestore START ===');
|
|
||||||
console.log('🔍 NOSTR_LOGIN_LITE: hasExtension:', this.hasExtension);
|
|
||||||
console.log('🔍 NOSTR_LOGIN_LITE: facadeInstalled:', this.facadeInstalled);
|
|
||||||
console.log('🔍 NOSTR_LOGIN_LITE: window.nostr:', window.nostr?.constructor?.name);
|
|
||||||
|
|
||||||
if (this.hasExtension) {
|
if (this.hasExtension) {
|
||||||
// EXTENSION MODE: Use custom extension persistence logic
|
// EXTENSION MODE: Use custom extension persistence logic
|
||||||
console.log('🔍 NOSTR_LOGIN_LITE: Extension mode - using extension-specific restore');
|
|
||||||
const restoredAuth = await this._attemptExtensionRestore();
|
const restoredAuth = await this._attemptExtensionRestore();
|
||||||
|
|
||||||
if (restoredAuth) {
|
if (restoredAuth) {
|
||||||
console.log('🔍 NOSTR_LOGIN_LITE: ✅ Extension auth restored successfully!');
|
|
||||||
return restoredAuth;
|
return restoredAuth;
|
||||||
} else {
|
} else {
|
||||||
console.log('🔍 NOSTR_LOGIN_LITE: ❌ Extension auth could not be restored');
|
console.log('🔍 NOSTR_LOGIN_LITE: ❌ Extension auth could not be restored');
|
||||||
@@ -1122,14 +1118,11 @@ class NostrLite {
|
|||||||
const restoredAuth = await window.nostr.restoreAuthState();
|
const restoredAuth = await window.nostr.restoreAuthState();
|
||||||
|
|
||||||
if (restoredAuth) {
|
if (restoredAuth) {
|
||||||
console.log('🔍 NOSTR_LOGIN_LITE: ✅ Facade auth restored successfully!');
|
|
||||||
console.log('🔍 NOSTR_LOGIN_LITE: Method:', restoredAuth.method);
|
|
||||||
console.log('🔍 NOSTR_LOGIN_LITE: Pubkey:', restoredAuth.pubkey);
|
|
||||||
|
|
||||||
// CRITICAL FIX: Activate facade resilience system for non-extension methods
|
// CRITICAL FIX: Activate facade resilience system for non-extension methods
|
||||||
// Extensions like nos2x can override our facade after page refresh
|
// Extensions like nos2x can override our facade after page refresh
|
||||||
if (restoredAuth.method === 'local' || restoredAuth.method === 'nip46') {
|
if (restoredAuth.method === 'local' || restoredAuth.method === 'nip46') {
|
||||||
console.log('🔍 NOSTR_LOGIN_LITE: 🛡️ Activating facade resilience system for page refresh');
|
|
||||||
this._activateResilienceProtection(restoredAuth.method);
|
this._activateResilienceProtection(restoredAuth.method);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1261,7 +1254,7 @@ class NostrLite {
|
|||||||
|
|
||||||
// Show prompt for NIP-46 reconnection
|
// Show prompt for NIP-46 reconnection
|
||||||
_showReconnectionPrompt(authData) {
|
_showReconnectionPrompt(authData) {
|
||||||
console.log('NOSTR_LOGIN_LITE: Showing reconnection prompt for NIP-46');
|
|
||||||
|
|
||||||
// Dispatch event that UI can listen to
|
// Dispatch event that UI can listen to
|
||||||
if (typeof window !== 'undefined') {
|
if (typeof window !== 'undefined') {
|
||||||
@@ -1393,10 +1386,10 @@ class AuthManager {
|
|||||||
// Configure storage type based on isolateSession option
|
// Configure storage type based on isolateSession option
|
||||||
if (options.isolateSession) {
|
if (options.isolateSession) {
|
||||||
this.storage = sessionStorage;
|
this.storage = sessionStorage;
|
||||||
console.log('🔐 AuthManager: Using sessionStorage for per-window isolation');
|
// console.log('🔐 AuthManager: Using sessionStorage for per-window isolation');
|
||||||
} else {
|
} else {
|
||||||
this.storage = localStorage;
|
this.storage = localStorage;
|
||||||
console.log('🔐 AuthManager: Using localStorage for cross-window persistence');
|
// console.log('🔐 AuthManager: Using localStorage for cross-window persistence');
|
||||||
}
|
}
|
||||||
|
|
||||||
console.warn('🔐 SECURITY: Private keys stored unencrypted in browser storage');
|
console.warn('🔐 SECURITY: Private keys stored unencrypted in browser storage');
|
||||||
@@ -1406,8 +1399,7 @@ class AuthManager {
|
|||||||
// Save authentication state using unified plaintext approach
|
// Save authentication state using unified plaintext approach
|
||||||
async saveAuthState(authData) {
|
async saveAuthState(authData) {
|
||||||
try {
|
try {
|
||||||
console.log('🔐 AuthManager: Saving auth state with plaintext storage');
|
|
||||||
console.warn('🔐 SECURITY: Private key will be stored unencrypted for maximum usability');
|
|
||||||
|
|
||||||
const authState = {
|
const authState = {
|
||||||
method: authData.method,
|
method: authData.method,
|
||||||
@@ -1423,15 +1415,14 @@ class AuthManager {
|
|||||||
hasGetPublicKey: typeof authData.extension?.getPublicKey === 'function',
|
hasGetPublicKey: typeof authData.extension?.getPublicKey === 'function',
|
||||||
hasSignEvent: typeof authData.extension?.signEvent === 'function'
|
hasSignEvent: typeof authData.extension?.signEvent === 'function'
|
||||||
};
|
};
|
||||||
console.log('🔐 AuthManager: Extension method - storing verification data only');
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'local':
|
case 'local':
|
||||||
// UNIFIED PLAINTEXT: Store secret key directly for maximum compatibility
|
// UNIFIED PLAINTEXT: Store secret key directly for maximum compatibility
|
||||||
if (authData.secret) {
|
if (authData.secret) {
|
||||||
authState.secret = authData.secret;
|
authState.secret = authData.secret;
|
||||||
console.log('🔐 AuthManager: Local method - storing secret key in plaintext');
|
|
||||||
console.warn('🔐 SECURITY: Secret key stored unencrypted for developer convenience');
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1443,13 +1434,13 @@ class AuthManager {
|
|||||||
relays: authData.signer.relays,
|
relays: authData.signer.relays,
|
||||||
// Don't store secret - user will need to reconnect
|
// Don't store secret - user will need to reconnect
|
||||||
};
|
};
|
||||||
console.log('🔐 AuthManager: NIP-46 method - storing connection parameters');
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'readonly':
|
case 'readonly':
|
||||||
// Read-only mode has no secrets to store
|
// Read-only mode has no secrets to store
|
||||||
console.log('🔐 AuthManager: Read-only method - storing basic auth state');
|
// console.log('🔐 AuthManager: Read-only method - storing basic auth state');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -1458,7 +1449,7 @@ class AuthManager {
|
|||||||
|
|
||||||
this.storage.setItem(this.storageKey, JSON.stringify(authState));
|
this.storage.setItem(this.storageKey, JSON.stringify(authState));
|
||||||
this.currentAuthState = authState;
|
this.currentAuthState = authState;
|
||||||
console.log('🔐 AuthManager: Auth state saved successfully for method:', authData.method);
|
// console.log('🔐 AuthManager: Auth state saved successfully for method:', authData.method);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('🔐 AuthManager: Failed to save auth state:', error);
|
console.error('🔐 AuthManager: Failed to save auth state:', error);
|
||||||
@@ -1469,11 +1460,10 @@ class AuthManager {
|
|||||||
// Restore authentication state on page load
|
// Restore authentication state on page load
|
||||||
async restoreAuthState() {
|
async restoreAuthState() {
|
||||||
try {
|
try {
|
||||||
console.log('🔍 AuthManager: === restoreAuthState START ===');
|
|
||||||
console.log('🔍 AuthManager: storageKey:', this.storageKey);
|
|
||||||
|
|
||||||
const stored = this.storage.getItem(this.storageKey);
|
const stored = this.storage.getItem(this.storageKey);
|
||||||
console.log('🔍 AuthManager: Storage raw value:', stored);
|
|
||||||
|
|
||||||
if (!stored) {
|
if (!stored) {
|
||||||
console.log('🔍 AuthManager: ❌ No stored auth state found');
|
console.log('🔍 AuthManager: ❌ No stored auth state found');
|
||||||
@@ -1481,10 +1471,7 @@ class AuthManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const authState = JSON.parse(stored);
|
const authState = JSON.parse(stored);
|
||||||
console.log('🔍 AuthManager: ✅ Parsed stored auth state:', authState);
|
|
||||||
console.log('🔍 AuthManager: Method:', authState.method);
|
|
||||||
console.log('🔍 AuthManager: Timestamp:', authState.timestamp);
|
|
||||||
console.log('🔍 AuthManager: Age (ms):', Date.now() - authState.timestamp);
|
|
||||||
|
|
||||||
// Check if stored state is too old (24 hours for most methods, 1 hour for extensions)
|
// Check if stored state is too old (24 hours for most methods, 1 hour for extensions)
|
||||||
const maxAge = authState.method === 'extension' ? 60 * 60 * 1000 : 24 * 60 * 60 * 1000;
|
const maxAge = authState.method === 'extension' ? 60 * 60 * 1000 : 24 * 60 * 60 * 1000;
|
||||||
@@ -1496,27 +1483,26 @@ class AuthManager {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('🔍 AuthManager: ✅ Auth state not expired, attempting restore for method:', authState.method);
|
|
||||||
|
|
||||||
let result;
|
let result;
|
||||||
switch (authState.method) {
|
switch (authState.method) {
|
||||||
case 'extension':
|
case 'extension':
|
||||||
console.log('🔍 AuthManager: Calling _restoreExtensionAuth...');
|
|
||||||
result = await this._restoreExtensionAuth(authState);
|
result = await this._restoreExtensionAuth(authState);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'local':
|
case 'local':
|
||||||
console.log('🔍 AuthManager: Calling _restoreLocalAuth...');
|
|
||||||
result = await this._restoreLocalAuth(authState);
|
result = await this._restoreLocalAuth(authState);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'nip46':
|
case 'nip46':
|
||||||
console.log('🔍 AuthManager: Calling _restoreNip46Auth...');
|
|
||||||
result = await this._restoreNip46Auth(authState);
|
result = await this._restoreNip46Auth(authState);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'readonly':
|
case 'readonly':
|
||||||
console.log('🔍 AuthManager: Calling _restoreReadonlyAuth...');
|
|
||||||
result = await this._restoreReadonlyAuth(authState);
|
result = await this._restoreReadonlyAuth(authState);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1525,8 +1511,6 @@ class AuthManager {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('🔍 AuthManager: Restore method result:', result);
|
|
||||||
console.log('🔍 AuthManager: === restoreAuthState END ===');
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -1552,19 +1536,14 @@ class AuthManager {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('🔍 AuthManager: ✅ Extension found:', extension.constructor?.name);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Verify extension still works and has same pubkey
|
// Verify extension still works and has same pubkey
|
||||||
const currentPubkey = await extension.getPublicKey();
|
const currentPubkey = await extension.getPublicKey();
|
||||||
if (currentPubkey !== authState.pubkey) {
|
|
||||||
console.log('🔍 AuthManager: ❌ Extension pubkey changed, not restoring');
|
|
||||||
console.log('🔍 AuthManager: Expected:', authState.pubkey);
|
|
||||||
console.log('🔍 AuthManager: Got:', currentPubkey);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('🔍 AuthManager: ✅ Extension auth restored successfully');
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
method: 'extension',
|
method: 'extension',
|
||||||
pubkey: authState.pubkey,
|
pubkey: authState.pubkey,
|
||||||
@@ -1572,16 +1551,14 @@ class AuthManager {
|
|||||||
};
|
};
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log('🔍 AuthManager: ❌ Extension verification failed:', error);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Smart extension waiting system - polls multiple locations for extensions
|
// Smart extension waiting system - polls multiple locations for extensions
|
||||||
async _waitForExtension(authState, maxWaitMs = 3000) {
|
async _waitForExtension(authState, maxWaitMs = 3000) {
|
||||||
console.log('🔍 AuthManager: === _waitForExtension START ===');
|
|
||||||
console.log('🔍 AuthManager: maxWaitMs:', maxWaitMs);
|
|
||||||
console.log('🔍 AuthManager: Looking for extension with constructor:', authState.extensionVerification?.constructor);
|
|
||||||
|
|
||||||
const startTime = Date.now();
|
const startTime = Date.now();
|
||||||
const pollInterval = 100; // Check every 100ms
|
const pollInterval = 100; // Check every 100ms
|
||||||
@@ -1599,13 +1576,13 @@ class AuthManager {
|
|||||||
];
|
];
|
||||||
|
|
||||||
while (Date.now() - startTime < maxWaitMs) {
|
while (Date.now() - startTime < maxWaitMs) {
|
||||||
console.log('🔍 AuthManager: Polling for extensions... (elapsed:', Date.now() - startTime, 'ms)');
|
|
||||||
|
|
||||||
// If our facade is currently installed and blocking, temporarily remove it
|
// If our facade is currently installed and blocking, temporarily remove it
|
||||||
let facadeRemoved = false;
|
let facadeRemoved = false;
|
||||||
let originalNostr = null;
|
let originalNostr = null;
|
||||||
if (window.nostr?.constructor?.name === 'WindowNostr') {
|
if (window.nostr?.constructor?.name === 'WindowNostr') {
|
||||||
console.log('🔍 AuthManager: Temporarily removing our facade to check for real extensions');
|
|
||||||
originalNostr = window.nostr;
|
originalNostr = window.nostr;
|
||||||
window.nostr = window.nostr.existingNostr || undefined;
|
window.nostr = window.nostr.existingNostr || undefined;
|
||||||
facadeRemoved = true;
|
facadeRemoved = true;
|
||||||
@@ -1616,21 +1593,21 @@ class AuthManager {
|
|||||||
for (const location of extensionLocations) {
|
for (const location of extensionLocations) {
|
||||||
try {
|
try {
|
||||||
const extension = location.getter();
|
const extension = location.getter();
|
||||||
console.log('🔍 AuthManager: Checking', location.path, ':', !!extension, extension?.constructor?.name);
|
|
||||||
|
|
||||||
if (this._isValidExtensionForRestore(extension, authState)) {
|
if (this._isValidExtensionForRestore(extension, authState)) {
|
||||||
console.log('🔍 AuthManager: ✅ Found matching extension at', location.path);
|
|
||||||
|
|
||||||
// Restore facade if we removed it
|
// Restore facade if we removed it
|
||||||
if (facadeRemoved && originalNostr) {
|
if (facadeRemoved && originalNostr) {
|
||||||
console.log('🔍 AuthManager: Restoring facade after finding extension');
|
|
||||||
window.nostr = originalNostr;
|
window.nostr = originalNostr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return extension;
|
return extension;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log('🔍 AuthManager: Error checking', location.path, ':', error.message);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1691,31 +1668,27 @@ class AuthManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('🔍 AuthManager: ✅ Extension validation passed for:', constructorName);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async _restoreLocalAuth(authState) {
|
async _restoreLocalAuth(authState) {
|
||||||
console.log('🔐 AuthManager: === _restoreLocalAuth (Unified Plaintext) ===');
|
|
||||||
|
|
||||||
// Check for legacy encrypted format first
|
|
||||||
if (authState.encrypted) {
|
if (authState.encrypted) {
|
||||||
console.log('🔐 AuthManager: Detected LEGACY encrypted format - migrating to plaintext');
|
|
||||||
console.warn('🔐 SECURITY: Converting from encrypted to plaintext storage for compatibility');
|
|
||||||
|
|
||||||
// Try to decrypt legacy format
|
// Try to decrypt legacy format
|
||||||
const sessionPassword = sessionStorage.getItem('nostr_session_key');
|
const sessionPassword = sessionStorage.getItem('nostr_session_key');
|
||||||
if (!sessionPassword) {
|
if (!sessionPassword) {
|
||||||
console.log('🔐 AuthManager: Legacy session password not found - user must re-login');
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.warn('🔐 AuthManager: Legacy encryption system no longer supported - user must re-login');
|
|
||||||
this.clearAuthState(); // Clear legacy format
|
this.clearAuthState(); // Clear legacy format
|
||||||
return null;
|
return null;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('🔐 AuthManager: Legacy decryption failed:', error);
|
|
||||||
this.clearAuthState(); // Clear corrupted legacy format
|
this.clearAuthState(); // Clear corrupted legacy format
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -1723,12 +1696,11 @@ class AuthManager {
|
|||||||
|
|
||||||
// NEW UNIFIED PLAINTEXT FORMAT
|
// NEW UNIFIED PLAINTEXT FORMAT
|
||||||
if (!authState.secret) {
|
if (!authState.secret) {
|
||||||
console.log('🔐 AuthManager: No secret found in plaintext format');
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('🔐 AuthManager: ✅ Local auth restored from plaintext storage');
|
|
||||||
console.warn('🔐 SECURITY: Secret key was stored unencrypted');
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
method: 'local',
|
method: 'local',
|
||||||
@@ -1739,14 +1711,14 @@ class AuthManager {
|
|||||||
|
|
||||||
async _restoreNip46Auth(authState) {
|
async _restoreNip46Auth(authState) {
|
||||||
if (!authState.nip46) {
|
if (!authState.nip46) {
|
||||||
console.log('🔐 AuthManager: No NIP-46 data found');
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For NIP-46, we can't automatically restore the connection
|
// For NIP-46, we can't automatically restore the connection
|
||||||
// because it requires the user to re-authenticate with the remote signer
|
// because it requires the user to re-authenticate with the remote signer
|
||||||
// Instead, we return the connection parameters so the UI can prompt for reconnection
|
// Instead, we return the connection parameters so the UI can prompt for reconnection
|
||||||
console.log('🔐 AuthManager: NIP-46 connection data found, requires user reconnection');
|
|
||||||
return {
|
return {
|
||||||
method: 'nip46',
|
method: 'nip46',
|
||||||
pubkey: authState.pubkey,
|
pubkey: authState.pubkey,
|
||||||
@@ -1756,7 +1728,7 @@ class AuthManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async _restoreReadonlyAuth(authState) {
|
async _restoreReadonlyAuth(authState) {
|
||||||
console.log('🔐 AuthManager: Read-only auth restored successfully');
|
|
||||||
return {
|
return {
|
||||||
method: 'readonly',
|
method: 'readonly',
|
||||||
pubkey: authState.pubkey
|
pubkey: authState.pubkey
|
||||||
@@ -1768,7 +1740,7 @@ class AuthManager {
|
|||||||
this.storage.removeItem(this.storageKey);
|
this.storage.removeItem(this.storageKey);
|
||||||
sessionStorage.removeItem('nostr_session_key'); // Clear legacy session key
|
sessionStorage.removeItem('nostr_session_key'); // Clear legacy session key
|
||||||
this.currentAuthState = null;
|
this.currentAuthState = null;
|
||||||
console.log('🔐 AuthManager: Auth state cleared from unified storage');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we have valid stored auth
|
// Check if we have valid stored auth
|
||||||
@@ -1811,8 +1783,8 @@ function getGlobalAuthManager() {
|
|||||||
// **UNIFIED GLOBAL FUNCTION**: Set authentication state (works for all methods)
|
// **UNIFIED GLOBAL FUNCTION**: Set authentication state (works for all methods)
|
||||||
function setAuthState(authData, options = {}) {
|
function setAuthState(authData, options = {}) {
|
||||||
try {
|
try {
|
||||||
console.log('🌐 setAuthState: Setting global auth state for method:', authData.method);
|
|
||||||
console.warn('🔐 SECURITY: Using unified plaintext storage for maximum compatibility');
|
|
||||||
|
|
||||||
// Store in memory
|
// Store in memory
|
||||||
globalAuthState = authData;
|
globalAuthState = authData;
|
||||||
@@ -1821,7 +1793,7 @@ function setAuthState(authData, options = {}) {
|
|||||||
const authManager = new AuthManager(options);
|
const authManager = new AuthManager(options);
|
||||||
authManager.saveAuthState(authData);
|
authManager.saveAuthState(authData);
|
||||||
|
|
||||||
console.log('🌐 setAuthState: Auth state saved successfully');
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('🌐 setAuthState: Failed to save auth state:', error);
|
console.error('🌐 setAuthState: Failed to save auth state:', error);
|
||||||
throw error;
|
throw error;
|
||||||
@@ -1844,13 +1816,13 @@ function getAuthState() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!stored) {
|
if (!stored) {
|
||||||
console.log('🌐 getAuthState: No auth state found in storage');
|
// console.log('🌐 getAuthState: No auth state found in storage');
|
||||||
globalAuthState = null;
|
globalAuthState = null;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const authState = JSON.parse(stored);
|
const authState = JSON.parse(stored);
|
||||||
console.log('🌐 getAuthState: Retrieved auth state:', authState.method);
|
// console.log('🌐 getAuthState: Retrieved auth state:', authState.method);
|
||||||
|
|
||||||
// Update in-memory cache
|
// Update in-memory cache
|
||||||
globalAuthState = authState;
|
globalAuthState = authState;
|
||||||
@@ -1866,7 +1838,7 @@ function getAuthState() {
|
|||||||
// **UNIFIED GLOBAL FUNCTION**: Clear authentication state (works for all methods)
|
// **UNIFIED GLOBAL FUNCTION**: Clear authentication state (works for all methods)
|
||||||
function clearAuthState() {
|
function clearAuthState() {
|
||||||
try {
|
try {
|
||||||
console.log('🌐 clearAuthState: Clearing global auth state');
|
// console.log('🌐 clearAuthState: Clearing global auth state');
|
||||||
|
|
||||||
// Clear in-memory state
|
// Clear in-memory state
|
||||||
globalAuthState = null;
|
globalAuthState = null;
|
||||||
@@ -1877,7 +1849,7 @@ function clearAuthState() {
|
|||||||
sessionStorage.removeItem(storageKey);
|
sessionStorage.removeItem(storageKey);
|
||||||
sessionStorage.removeItem('nostr_session_key'); // Clear legacy session key
|
sessionStorage.removeItem('nostr_session_key'); // Clear legacy session key
|
||||||
|
|
||||||
console.log('🌐 clearAuthState: Auth state cleared from all storage locations');
|
// console.log('🌐 clearAuthState: Auth state cleared from all storage locations');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('🌐 clearAuthState: Failed to clear auth state:', error);
|
console.error('🌐 clearAuthState: Failed to clear auth state:', error);
|
||||||
}
|
}
|
||||||
@@ -2260,9 +2232,9 @@ if (typeof window !== 'undefined') {
|
|||||||
_instance: nostrLite
|
_instance: nostrLite
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('NOSTR_LOGIN_LITE: Library loaded and ready');
|
// console.log('NOSTR_LOGIN_LITE: Library loaded and ready');
|
||||||
console.log('NOSTR_LOGIN_LITE: Use window.NOSTR_LOGIN_LITE.init(options) to initialize');
|
// console.log('NOSTR_LOGIN_LITE: Use window.NOSTR_LOGIN_LITE.init(options) to initialize');
|
||||||
console.log('NOSTR_LOGIN_LITE: Detected', nostrLite.extensionBridge.getExtensionCount(), 'browser extensions');
|
// console.log('NOSTR_LOGIN_LITE: Detected', nostrLite.extensionBridge.getExtensionCount(), 'browser extensions');
|
||||||
console.warn('🔐 SECURITY: Unified plaintext storage enabled for maximum developer usability');
|
console.warn('🔐 SECURITY: Unified plaintext storage enabled for maximum developer usability');
|
||||||
} else {
|
} else {
|
||||||
// Node.js environment
|
// Node.js environment
|
||||||
@@ -2284,16 +2256,16 @@ if (typeof window !== 'undefined') {
|
|||||||
const hasNostrLite = bundle.includes('NOSTR_LOGIN_LITE');
|
const hasNostrLite = bundle.includes('NOSTR_LOGIN_LITE');
|
||||||
const hasThemeCss = bundle.includes('THEME_CSS');
|
const hasThemeCss = bundle.includes('THEME_CSS');
|
||||||
|
|
||||||
console.log('\n📋 Bundle contents:');
|
// console.log('\n📋 Bundle contents:');
|
||||||
console.log(' Modal UI: ' + (hasModal ? '✅ Included' : '❌ Missing'));
|
// console.log(' Modal UI: ' + (hasModal ? '✅ Included' : '❌ Missing'));
|
||||||
console.log(' NOSTR_LOGIN_LITE: ' + (hasNostrLite ? '✅ Included' : '❌ Missing'));
|
// console.log(' NOSTR_LOGIN_LITE: ' + (hasNostrLite ? '✅ Included' : '❌ Missing'));
|
||||||
console.log(' CSS-Only Themes: ' + (hasThemeCss ? '✅ Included' : '❌ Missing'));
|
// console.log(' CSS-Only Themes: ' + (hasThemeCss ? '✅ Included' : '❌ Missing'));
|
||||||
console.log(' Extension Bridge: ✅ Included');
|
// console.log(' Extension Bridge: ✅ Included');
|
||||||
console.log(' Window.nostr facade: ✅ Included');
|
// console.log(' Window.nostr facade: ✅ Included');
|
||||||
|
|
||||||
console.log('\n📋 Two-file architecture:');
|
// console.log('\n📋 Two-file architecture:');
|
||||||
console.log(' 1. nostr.bundle.js (official nostr-tools - 220KB)');
|
// console.log(' 1. nostr.bundle.js (official nostr-tools - 220KB)');
|
||||||
console.log(' 2. nostr-lite.js (NOSTR_LOGIN_LITE with CSS-only themes - ' + sizeKB + 'KB)');
|
// console.log(' 2. nostr-lite.js (NOSTR_LOGIN_LITE with CSS-only themes - ' + sizeKB + 'KB)');
|
||||||
|
|
||||||
return bundle;
|
return bundle;
|
||||||
}
|
}
|
||||||
@@ -330,7 +330,7 @@ class Modal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_handleOptionClick(type) {
|
_handleOptionClick(type) {
|
||||||
console.log('Selected login type:', type);
|
// console.log('Selected login type:', type);
|
||||||
|
|
||||||
// Handle different login types
|
// Handle different login types
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@@ -362,16 +362,16 @@ class Modal {
|
|||||||
// Check if NostrLite instance has a preserved extension (real extension detected at init)
|
// Check if NostrLite instance has a preserved extension (real extension detected at init)
|
||||||
if (window.NOSTR_LOGIN_LITE?._instance?.preservedExtension) {
|
if (window.NOSTR_LOGIN_LITE?._instance?.preservedExtension) {
|
||||||
extension = window.NOSTR_LOGIN_LITE._instance.preservedExtension;
|
extension = window.NOSTR_LOGIN_LITE._instance.preservedExtension;
|
||||||
console.log('Modal: Using preserved extension:', extension.constructor?.name);
|
// console.log('Modal: Using preserved extension:', extension.constructor?.name);
|
||||||
}
|
}
|
||||||
// Otherwise check current window.nostr
|
// Otherwise check current window.nostr
|
||||||
else if (window.nostr && this._isRealExtension(window.nostr)) {
|
else if (window.nostr && this._isRealExtension(window.nostr)) {
|
||||||
extension = window.nostr;
|
extension = window.nostr;
|
||||||
console.log('Modal: Using current window.nostr extension:', extension.constructor?.name);
|
// console.log('Modal: Using current window.nostr extension:', extension.constructor?.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!extension) {
|
if (!extension) {
|
||||||
console.log('Modal: No extension detected yet, waiting for deferred detection...');
|
// console.log('Modal: No extension detected yet, waiting for deferred detection...');
|
||||||
|
|
||||||
// DEFERRED EXTENSION CHECK: Extensions like nos2x might load after our library
|
// DEFERRED EXTENSION CHECK: Extensions like nos2x might load after our library
|
||||||
let attempts = 0;
|
let attempts = 0;
|
||||||
@@ -382,7 +382,7 @@ class Modal {
|
|||||||
// Check again for preserved extension (might be set by deferred detection)
|
// Check again for preserved extension (might be set by deferred detection)
|
||||||
if (window.NOSTR_LOGIN_LITE?._instance?.preservedExtension) {
|
if (window.NOSTR_LOGIN_LITE?._instance?.preservedExtension) {
|
||||||
extension = window.NOSTR_LOGIN_LITE._instance.preservedExtension;
|
extension = window.NOSTR_LOGIN_LITE._instance.preservedExtension;
|
||||||
console.log('Modal: Found preserved extension after waiting:', extension.constructor?.name);
|
// console.log('Modal: Found preserved extension after waiting:', extension.constructor?.name);
|
||||||
this._tryExtensionLogin(extension);
|
this._tryExtensionLogin(extension);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -390,7 +390,7 @@ class Modal {
|
|||||||
// Check current window.nostr again
|
// Check current window.nostr again
|
||||||
if (window.nostr && this._isRealExtension(window.nostr)) {
|
if (window.nostr && this._isRealExtension(window.nostr)) {
|
||||||
extension = window.nostr;
|
extension = window.nostr;
|
||||||
console.log('Modal: Found extension at window.nostr after waiting:', extension.constructor?.name);
|
// console.log('Modal: Found extension at window.nostr after waiting:', extension.constructor?.name);
|
||||||
this._tryExtensionLogin(extension);
|
this._tryExtensionLogin(extension);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -399,7 +399,7 @@ class Modal {
|
|||||||
if (attempts < maxAttempts) {
|
if (attempts < maxAttempts) {
|
||||||
setTimeout(checkForExtension, 200);
|
setTimeout(checkForExtension, 200);
|
||||||
} else {
|
} else {
|
||||||
console.log('Modal: No browser extension found after waiting 2 seconds');
|
// console.log('Modal: No browser extension found after waiting 2 seconds');
|
||||||
this._showExtensionRequired();
|
this._showExtensionRequired();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -410,7 +410,7 @@ class Modal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use the single detected extension directly - no choice UI
|
// Use the single detected extension directly - no choice UI
|
||||||
console.log('Modal: Single extension mode - using extension directly');
|
// console.log('Modal: Single extension mode - using extension directly');
|
||||||
this._tryExtensionLogin(extension);
|
this._tryExtensionLogin(extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -435,7 +435,7 @@ class Modal {
|
|||||||
try {
|
try {
|
||||||
const obj = location.getter();
|
const obj = location.getter();
|
||||||
|
|
||||||
console.log(`Modal: Checking ${location.name}:`, !!obj, obj?.constructor?.name);
|
// console.log(`Modal: Checking ${location.name}:`, !!obj, obj?.constructor?.name);
|
||||||
|
|
||||||
if (obj && this._isRealExtension(obj) && !seenExtensions.has(obj)) {
|
if (obj && this._isRealExtension(obj) && !seenExtensions.has(obj)) {
|
||||||
extensions.push({
|
extensions.push({
|
||||||
@@ -445,25 +445,25 @@ class Modal {
|
|||||||
extension: obj
|
extension: obj
|
||||||
});
|
});
|
||||||
seenExtensions.add(obj);
|
seenExtensions.add(obj);
|
||||||
console.log(`Modal: ✓ Detected extension at ${location.name} (${obj.constructor?.name})`);
|
// console.log(`Modal: ✓ Detected extension at ${location.name} (${obj.constructor?.name})`);
|
||||||
} else if (obj) {
|
} else if (obj) {
|
||||||
console.log(`Modal: ✗ Filtered out ${location.name} (${obj.constructor?.name})`);
|
// console.log(`Modal: ✗ Filtered out ${location.name} (${obj.constructor?.name})`);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Location doesn't exist or can't be accessed
|
// Location doesn't exist or can't be accessed
|
||||||
console.log(`Modal: ${location.name} not accessible:`, e.message);
|
// console.log(`Modal: ${location.name} not accessible:`, e.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Also check window.nostr but be extra careful to avoid our library
|
// Also check window.nostr but be extra careful to avoid our library
|
||||||
console.log('Modal: Checking window.nostr:', !!window.nostr, window.nostr?.constructor?.name);
|
// console.log('Modal: Checking window.nostr:', !!window.nostr, window.nostr?.constructor?.name);
|
||||||
|
|
||||||
if (window.nostr) {
|
if (window.nostr) {
|
||||||
// Check if window.nostr is our WindowNostr facade with a preserved extension
|
// Check if window.nostr is our WindowNostr facade with a preserved extension
|
||||||
if (window.nostr.constructor?.name === 'WindowNostr' && window.nostr.existingNostr) {
|
if (window.nostr.constructor?.name === 'WindowNostr' && window.nostr.existingNostr) {
|
||||||
console.log('Modal: Found WindowNostr facade, checking existingNostr for preserved extension');
|
// console.log('Modal: Found WindowNostr facade, checking existingNostr for preserved extension');
|
||||||
const preservedExtension = window.nostr.existingNostr;
|
const preservedExtension = window.nostr.existingNostr;
|
||||||
console.log('Modal: Preserved extension:', !!preservedExtension, preservedExtension?.constructor?.name);
|
// console.log('Modal: Preserved extension:', !!preservedExtension, preservedExtension?.constructor?.name);
|
||||||
|
|
||||||
if (preservedExtension && this._isRealExtension(preservedExtension) && !seenExtensions.has(preservedExtension)) {
|
if (preservedExtension && this._isRealExtension(preservedExtension) && !seenExtensions.has(preservedExtension)) {
|
||||||
extensions.push({
|
extensions.push({
|
||||||
@@ -473,7 +473,7 @@ class Modal {
|
|||||||
extension: preservedExtension
|
extension: preservedExtension
|
||||||
});
|
});
|
||||||
seenExtensions.add(preservedExtension);
|
seenExtensions.add(preservedExtension);
|
||||||
console.log(`Modal: ✓ Detected preserved extension: ${preservedExtension.constructor?.name}`);
|
// console.log(`Modal: ✓ Detected preserved extension: ${preservedExtension.constructor?.name}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check if window.nostr is directly a real extension (not our facade)
|
// Check if window.nostr is directly a real extension (not our facade)
|
||||||
@@ -485,9 +485,9 @@ class Modal {
|
|||||||
extension: window.nostr
|
extension: window.nostr
|
||||||
});
|
});
|
||||||
seenExtensions.add(window.nostr);
|
seenExtensions.add(window.nostr);
|
||||||
console.log(`Modal: ✓ Detected extension at window.nostr: ${window.nostr.constructor?.name}`);
|
// console.log(`Modal: ✓ Detected extension at window.nostr: ${window.nostr.constructor?.name}`);
|
||||||
} else {
|
} else {
|
||||||
console.log(`Modal: ✗ Filtered out window.nostr (${window.nostr.constructor?.name}) - not a real extension`);
|
// console.log(`Modal: ✗ Filtered out window.nostr (${window.nostr.constructor?.name}) - not a real extension`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -495,27 +495,27 @@ class Modal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_isRealExtension(obj) {
|
_isRealExtension(obj) {
|
||||||
console.log(`Modal: EXTENSIVE DEBUG - _isRealExtension called with:`, obj);
|
// console.log(`Modal: EXTENSIVE DEBUG - _isRealExtension called with:`, obj);
|
||||||
console.log(`Modal: Object type: ${typeof obj}`);
|
// console.log(`Modal: Object type: ${typeof obj}`);
|
||||||
console.log(`Modal: Object truthy: ${!!obj}`);
|
// console.log(`Modal: Object truthy: ${!!obj}`);
|
||||||
|
|
||||||
if (!obj || typeof obj !== 'object') {
|
if (!obj || typeof obj !== 'object') {
|
||||||
console.log(`Modal: REJECT - Not an object`);
|
// console.log(`Modal: REJECT - Not an object`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`Modal: getPublicKey type: ${typeof obj.getPublicKey}`);
|
// console.log(`Modal: getPublicKey type: ${typeof obj.getPublicKey}`);
|
||||||
console.log(`Modal: signEvent type: ${typeof obj.signEvent}`);
|
// console.log(`Modal: signEvent type: ${typeof obj.signEvent}`);
|
||||||
|
|
||||||
// Must have required Nostr methods
|
// Must have required Nostr methods
|
||||||
if (typeof obj.getPublicKey !== 'function' || typeof obj.signEvent !== 'function') {
|
if (typeof obj.getPublicKey !== 'function' || typeof obj.signEvent !== 'function') {
|
||||||
console.log(`Modal: REJECT - Missing required methods`);
|
// console.log(`Modal: REJECT - Missing required methods`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exclude NostrTools library object
|
// Exclude NostrTools library object
|
||||||
if (obj === window.NostrTools) {
|
if (obj === window.NostrTools) {
|
||||||
console.log(`Modal: REJECT - Is NostrTools object`);
|
// console.log(`Modal: REJECT - Is NostrTools object`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -524,8 +524,8 @@ class Modal {
|
|||||||
const constructorName = obj.constructor?.name;
|
const constructorName = obj.constructor?.name;
|
||||||
const objectKeys = Object.keys(obj);
|
const objectKeys = Object.keys(obj);
|
||||||
|
|
||||||
console.log(`Modal: Constructor name: "${constructorName}"`);
|
// console.log(`Modal: Constructor name: "${constructorName}"`);
|
||||||
console.log(`Modal: Object keys: [${objectKeys.join(', ')}]`);
|
// console.log(`Modal: Object keys: [${objectKeys.join(', ')}]`);
|
||||||
|
|
||||||
// COMPREHENSIVE TEST LOGIC - Accept anything with required methods that's not our specific library classes
|
// COMPREHENSIVE TEST LOGIC - Accept anything with required methods that's not our specific library classes
|
||||||
const isRealExtension = (
|
const isRealExtension = (
|
||||||
@@ -535,12 +535,12 @@ class Modal {
|
|||||||
constructorName !== 'NostrLite' // Our main class
|
constructorName !== 'NostrLite' // Our main class
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log(`Modal: Using comprehensive test logic:`);
|
// console.log(`Modal: Using comprehensive test logic:`);
|
||||||
console.log(` Has getPublicKey: ${typeof obj.getPublicKey === 'function'}`);
|
// console.log(` Has getPublicKey: ${typeof obj.getPublicKey === 'function'}`);
|
||||||
console.log(` Has signEvent: ${typeof obj.signEvent === 'function'}`);
|
// console.log(` Has signEvent: ${typeof obj.signEvent === 'function'}`);
|
||||||
console.log(` Not WindowNostr: ${constructorName !== 'WindowNostr'}`);
|
// console.log(` Not WindowNostr: ${constructorName !== 'WindowNostr'}`);
|
||||||
console.log(` Not NostrLite: ${constructorName !== 'NostrLite'}`);
|
// console.log(` Not NostrLite: ${constructorName !== 'NostrLite'}`);
|
||||||
console.log(` Constructor: "${constructorName}"`);
|
// console.log(` Constructor: "${constructorName}"`);
|
||||||
|
|
||||||
// Additional debugging for comparison
|
// Additional debugging for comparison
|
||||||
const extensionPropChecks = {
|
const extensionPropChecks = {
|
||||||
@@ -556,7 +556,7 @@ class Modal {
|
|||||||
description: !!obj.description
|
description: !!obj.description
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log(`Modal: Extension property analysis:`, extensionPropChecks);
|
// console.log(`Modal: Extension property analysis:`, extensionPropChecks);
|
||||||
|
|
||||||
const hasExtensionProps = !!(
|
const hasExtensionProps = !!(
|
||||||
obj._isEnabled || obj.enabled || obj.kind ||
|
obj._isEnabled || obj.enabled || obj.kind ||
|
||||||
@@ -566,15 +566,15 @@ class Modal {
|
|||||||
|
|
||||||
const underscoreKeys = objectKeys.filter(key => key.startsWith('_'));
|
const underscoreKeys = objectKeys.filter(key => key.startsWith('_'));
|
||||||
const hexToUint8Keys = objectKeys.filter(key => key.startsWith('_hex'));
|
const hexToUint8Keys = objectKeys.filter(key => key.startsWith('_hex'));
|
||||||
console.log(`Modal: Underscore keys: [${underscoreKeys.join(', ')}]`);
|
// console.log(`Modal: Underscore keys: [${underscoreKeys.join(', ')}]`);
|
||||||
console.log(`Modal: _hex* keys: [${hexToUint8Keys.join(', ')}]`);
|
// console.log(`Modal: _hex* keys: [${hexToUint8Keys.join(', ')}]`);
|
||||||
|
|
||||||
console.log(`Modal: Additional analysis:`);
|
// console.log(`Modal: Additional analysis:`);
|
||||||
console.log(` hasExtensionProps: ${hasExtensionProps}`);
|
// console.log(` hasExtensionProps: ${hasExtensionProps}`);
|
||||||
console.log(` hasLibraryMethod (_hexToUint8Array): ${objectKeys.includes('_hexToUint8Array')}`);
|
// console.log(` hasLibraryMethod (_hexToUint8Array): ${objectKeys.includes('_hexToUint8Array')}`);
|
||||||
|
|
||||||
console.log(`Modal: COMPREHENSIVE TEST LOGIC RESULT: ${isRealExtension ? 'ACCEPT' : 'REJECT'}`);
|
// console.log(`Modal: COMPREHENSIVE TEST LOGIC RESULT: ${isRealExtension ? 'ACCEPT' : 'REJECT'}`);
|
||||||
console.log(`Modal: FINAL DECISION for ${constructorName}: ${isRealExtension ? 'ACCEPT' : 'REJECT'}`);
|
// console.log(`Modal: FINAL DECISION for ${constructorName}: ${isRealExtension ? 'ACCEPT' : 'REJECT'}`);
|
||||||
|
|
||||||
return isRealExtension;
|
return isRealExtension;
|
||||||
}
|
}
|
||||||
@@ -828,7 +828,7 @@ class Modal {
|
|||||||
textarea.oninput();
|
textarea.oninput();
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Generated new local secret key (nsec format)');
|
// console.log('Generated new local secret key (nsec format)');
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to generate local key:', error);
|
console.error('Failed to generate local key:', error);
|
||||||
@@ -1131,15 +1131,15 @@ class Modal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_setAuthMethod(method, options = {}) {
|
_setAuthMethod(method, options = {}) {
|
||||||
console.log('Modal: _setAuthMethod called with:', method, options);
|
// console.log('Modal: _setAuthMethod called with:', method, options);
|
||||||
|
|
||||||
// CRITICAL: Never install facade for extension methods - leave window.nostr as the extension
|
// CRITICAL: Never install facade for extension methods - leave window.nostr as the extension
|
||||||
if (method === 'extension') {
|
if (method === 'extension') {
|
||||||
console.log('Modal: Extension method - NOT installing facade, leaving window.nostr as extension');
|
// console.log('Modal: Extension method - NOT installing facade, leaving window.nostr as extension');
|
||||||
|
|
||||||
// Save extension authentication state using global setAuthState function
|
// Save extension authentication state using global setAuthState function
|
||||||
if (typeof window.setAuthState === 'function') {
|
if (typeof window.setAuthState === 'function') {
|
||||||
console.log('Modal: Saving extension auth state to storage');
|
// console.log('Modal: Saving extension auth state to storage');
|
||||||
window.setAuthState({ method, ...options }, { isolateSession: this.options?.isolateSession });
|
window.setAuthState({ method, ...options }, { isolateSession: this.options?.isolateSession });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1154,7 +1154,7 @@ class Modal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FOR NON-EXTENSION METHODS: Force-install facade with resilience
|
// FOR NON-EXTENSION METHODS: Force-install facade with resilience
|
||||||
console.log('Modal: Non-extension method - FORCE-INSTALLING facade with resilience:', method);
|
// console.log('Modal: Non-extension method - FORCE-INSTALLING facade with resilience:', method);
|
||||||
|
|
||||||
// Store the current extension if any (for potential restoration later)
|
// Store the current extension if any (for potential restoration later)
|
||||||
const currentExtension = (window.nostr?.constructor?.name !== 'WindowNostr') ? window.nostr : null;
|
const currentExtension = (window.nostr?.constructor?.name !== 'WindowNostr') ? window.nostr : null;
|
||||||
@@ -1173,10 +1173,10 @@ class Modal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IMMEDIATE FACADE INSTALLATION
|
// IMMEDIATE FACADE INSTALLATION
|
||||||
console.log('Modal: Installing WindowNostr facade immediately for method:', method);
|
// console.log('Modal: Installing WindowNostr facade immediately for method:', method);
|
||||||
const preservedExtension = nostrLiteInstance.preservedExtension || currentExtension;
|
const preservedExtension = nostrLiteInstance.preservedExtension || currentExtension;
|
||||||
nostrLiteInstance._installFacade(preservedExtension, true);
|
nostrLiteInstance._installFacade(preservedExtension, true);
|
||||||
console.log('Modal: WindowNostr facade force-installed, current window.nostr:', window.nostr?.constructor?.name);
|
// console.log('Modal: WindowNostr facade force-installed, current window.nostr:', window.nostr?.constructor?.name);
|
||||||
|
|
||||||
// DELAYED FACADE RESILIENCE - Reinstall after extension override attempts
|
// DELAYED FACADE RESILIENCE - Reinstall after extension override attempts
|
||||||
const forceReinstallFacade = () => {
|
const forceReinstallFacade = () => {
|
||||||
@@ -1201,9 +1201,9 @@ class Modal {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Schedule resilience checks at multiple intervals
|
// Schedule resilience checks at multiple intervals
|
||||||
setTimeout(forceReinstallFacade, 100); // Quick check
|
// setTimeout(forceReinstallFacade, 100); // Quick check
|
||||||
setTimeout(forceReinstallFacade, 500); // Main check
|
// setTimeout(forceReinstallFacade, 500); // Main check
|
||||||
setTimeout(forceReinstallFacade, 1500); // Final check
|
// setTimeout(forceReinstallFacade, 1500); // Final check
|
||||||
|
|
||||||
// Emit auth method selection
|
// Emit auth method selection
|
||||||
const event = new CustomEvent('nlMethodSelected', {
|
const event = new CustomEvent('nlMethodSelected', {
|
||||||
@@ -1390,7 +1390,7 @@ class Modal {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log('Bunker key validation failed:', error.message);
|
// console.log('Bunker key validation failed:', error.message);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1443,7 +1443,7 @@ class Modal {
|
|||||||
|
|
||||||
async _performNip46Connect(bunkerPubkey) {
|
async _performNip46Connect(bunkerPubkey) {
|
||||||
try {
|
try {
|
||||||
console.log('Starting NIP-46 connection to bunker:', bunkerPubkey);
|
// console.log('Starting NIP-46 connection to bunker:', bunkerPubkey);
|
||||||
|
|
||||||
// Check if nostr-tools NIP-46 is available
|
// Check if nostr-tools NIP-46 is available
|
||||||
if (!window.NostrTools?.nip46) {
|
if (!window.NostrTools?.nip46) {
|
||||||
@@ -1451,41 +1451,41 @@ class Modal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use nostr-tools to parse bunker input - this handles all formats correctly
|
// Use nostr-tools to parse bunker input - this handles all formats correctly
|
||||||
console.log('Parsing bunker input with nostr-tools...');
|
// console.log('Parsing bunker input with nostr-tools...');
|
||||||
const bunkerPointer = await window.NostrTools.nip46.parseBunkerInput(bunkerPubkey);
|
const bunkerPointer = await window.NostrTools.nip46.parseBunkerInput(bunkerPubkey);
|
||||||
|
|
||||||
if (!bunkerPointer) {
|
if (!bunkerPointer) {
|
||||||
throw new Error('Unable to parse bunker connection string or resolve NIP-05 identifier');
|
throw new Error('Unable to parse bunker connection string or resolve NIP-05 identifier');
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Parsed bunker pointer:', bunkerPointer);
|
// console.log('Parsed bunker pointer:', bunkerPointer);
|
||||||
|
|
||||||
// Create local client keypair for this session
|
// Create local client keypair for this session
|
||||||
const localSecretKey = window.NostrTools.generateSecretKey();
|
const localSecretKey = window.NostrTools.generateSecretKey();
|
||||||
console.log('Generated local client keypair for NIP-46 session');
|
// console.log('Generated local client keypair for NIP-46 session');
|
||||||
|
|
||||||
// Use nostr-tools BunkerSigner factory method (not constructor - it's private)
|
// Use nostr-tools BunkerSigner factory method (not constructor - it's private)
|
||||||
console.log('Creating nip46 BunkerSigner...');
|
// console.log('Creating nip46 BunkerSigner...');
|
||||||
const signer = window.NostrTools.nip46.BunkerSigner.fromBunker(localSecretKey, bunkerPointer, {
|
const signer = window.NostrTools.nip46.BunkerSigner.fromBunker(localSecretKey, bunkerPointer, {
|
||||||
onauth: (url) => {
|
onauth: (url) => {
|
||||||
console.log('Received auth URL from bunker:', url);
|
// console.log('Received auth URL from bunker:', url);
|
||||||
// Open auth URL in popup or redirect
|
// Open auth URL in popup or redirect
|
||||||
window.open(url, '_blank', 'width=600,height=800');
|
window.open(url, '_blank', 'width=600,height=800');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('NIP-46 BunkerSigner created successfully');
|
// console.log('NIP-46 BunkerSigner created successfully');
|
||||||
|
|
||||||
// Skip ping test - NIP-46 works through relays, not direct connection
|
// Skip ping test - NIP-46 works through relays, not direct connection
|
||||||
// Try to connect directly (this may trigger auth flow)
|
// Try to connect directly (this may trigger auth flow)
|
||||||
console.log('Attempting NIP-46 connect...');
|
// console.log('Attempting NIP-46 connect...');
|
||||||
await signer.connect();
|
await signer.connect();
|
||||||
console.log('NIP-46 connect successful');
|
// console.log('NIP-46 connect successful');
|
||||||
|
|
||||||
// Get the user's public key from the bunker
|
// Get the user's public key from the bunker
|
||||||
console.log('Getting public key from bunker...');
|
// console.log('Getting public key from bunker...');
|
||||||
const userPubkey = await signer.getPublicKey();
|
const userPubkey = await signer.getPublicKey();
|
||||||
console.log('NIP-46 user public key:', userPubkey);
|
// console.log('NIP-46 user public key:', userPubkey);
|
||||||
|
|
||||||
// Store the NIP-46 authentication info
|
// Store the NIP-46 authentication info
|
||||||
const nip46Info = {
|
const nip46Info = {
|
||||||
@@ -1499,7 +1499,7 @@ class Modal {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('NOSTR_LOGIN_LITE NIP-46 connection established successfully!');
|
// console.log('NOSTR_LOGIN_LITE NIP-46 connection established successfully!');
|
||||||
|
|
||||||
// Set as current auth method
|
// Set as current auth method
|
||||||
this._setAuthMethod('nip46', nip46Info);
|
this._setAuthMethod('nip46', nip46Info);
|
||||||
@@ -1672,7 +1672,7 @@ class Modal {
|
|||||||
textarea.oninput();
|
textarea.oninput();
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Generated new seed phrase:', mnemonic.split(/\s+/).length, 'words');
|
// console.log('Generated new seed phrase:', mnemonic.split(/\s+/).length, 'words');
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to generate seed phrase:', error);
|
console.error('Failed to generate seed phrase:', error);
|
||||||
@@ -1700,7 +1700,7 @@ class Modal {
|
|||||||
window.NostrTools.nip06.privateKeyFromSeedWords(mnemonic, '', 0);
|
window.NostrTools.nip06.privateKeyFromSeedWords(mnemonic, '', 0);
|
||||||
return true;
|
return true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log('Mnemonic validation failed:', error.message);
|
// console.log('Mnemonic validation failed:', error.message);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1742,7 +1742,7 @@ class Modal {
|
|||||||
throw new Error('Failed to derive any accounts from seed phrase');
|
throw new Error('Failed to derive any accounts from seed phrase');
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`Successfully derived ${accounts.length} accounts from seed phrase`);
|
// console.log(`Successfully derived ${accounts.length} accounts from seed phrase`);
|
||||||
this._showAccountSelection(accounts);
|
this._showAccountSelection(accounts);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -1838,7 +1838,7 @@ class Modal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_selectAccount(account) {
|
_selectAccount(account) {
|
||||||
console.log('Selected account:', account.index, account.npub);
|
// console.log('Selected account:', account.index, account.npub);
|
||||||
|
|
||||||
// Use the same auth method as local keys, but with seedphrase identifier
|
// Use the same auth method as local keys, but with seedphrase identifier
|
||||||
this._setAuthMethod('local', {
|
this._setAuthMethod('local', {
|
||||||
Reference in New Issue
Block a user