# NOSTR_LOGIN_LITE - Login Logic Analysis

This document explains the complete login and authentication flow for the NOSTR_LOGIN_LITE library, including how state is maintained upon page refresh.

## System Architecture Overview

The library uses a **modular authentication architecture** with these key components:

1. **FloatingTab** - UI component for login trigger and status display
2. **Modal** - UI component for authentication method selection
3. **NostrLite** - Main library coordinator and facade manager
4. **WindowNostr** - NIP-07 compliant facade for non-extension methods
5. **AuthManager** - Persistent state management with encryption
6. **Extension Bridge** - Browser extension detection and management

## Authentication Flow Diagrams

### Initial Page Load Flow

```
┌─────────────────────┐
│   Page Loads        │
└─────────┬───────────┘
          │
          ▼
┌─────────────────────┐
│ NOSTR_LOGIN_LITE    │
│ .init() called      │
└─────────┬───────────┘
          │
          ▼
┌─────────────────────┐    YES    ┌─────────────────────┐
│ Real extension      │──────────▶│ Extension-First     │
│ detected?           │           │ Mode: Don't install │
└─────────┬───────────┘           │ facade              │
          │ NO                    └─────────────────────┘
          ▼
┌─────────────────────┐
│ Install WindowNostr │
│ facade for local/   │
│ NIP-46/readonly     │
└─────────┬───────────┘
          │
          ▼
┌─────────────────────┐    YES    ┌─────────────────────┐
│ Persistence         │──────────▶│ _attemptAuthRestore │
│ enabled?            │           │ called              │
└─────────┬───────────┘           └─────────┬───────────┘
          │ NO                              │
          ▼                                 ▼
┌─────────────────────┐           ┌─────────────────────┐
│ Initialization      │           │ Check storage for   │
│ complete            │           │ saved auth state    │
└─────────────────────┘           └─────────┬───────────┘
                                            │
                                            ▼
                                  ┌─────────────────────┐    YES
                                  │ Valid auth state    │────────┐
                                  │ found?              │        │
                                  └─────────┬───────────┘        │
                                            │ NO                 │
                                            ▼                    ▼
                                  ┌─────────────────────┐  ┌─────────────────────┐
                                  │ Show login UI       │  │ Restore auth &      │
                                  │ (FloatingTab,etc)   │  │ dispatch events     │
                                  └─────────────────────┘  └─────────────────────┘
```

### User-Initiated Login Flow

```
┌─────────────────────┐         ┌─────────────────────┐
│ User clicks         │         │ User clicks         │
│ FloatingTab         │         │ Login Button        │
└─────────┬───────────┘         └─────────┬───────────┘
          │                               │
          ▼                               ▼
┌─────────────────────┐                   │
│ Extension           │                   │
│ available?          │                   │
└─────────┬───────────┘                   │
          │ YES                           │
          ▼                               │
┌─────────────────────┐                   │
│ Auto-try extension  │                   │
│ authentication      │                   │
└─────────┬───────────┘                   │
          │ SUCCESS                       │
          ▼                               │
┌─────────────────────┐                   │
│ Authentication      │                   │
│ complete            │◀──────────────────┘
└─────────────────────┘         │ FAIL OR ALWAYS
                                ▼
                      ┌─────────────────────┐
                      │ Open Modal with     │
                      │ method selection:   │
                      │ • Extension         │
                      │ • Local Key         │
                      │ • NIP-46 Connect    │
                      │ • Read-only         │
                      │ • OTP/DM            │
                      └─────────┬───────────┘
                                │
                                ▼
                      ┌─────────────────────┐
                      │ User selects method │
                      │ and completes auth  │
                      └─────────┬───────────┘
                                │
                                ▼
                      ┌─────────────────────┐
                      │ Authentication      │
                      │ complete            │
                      └─────────────────────┘
```

### Authentication Storage & Persistence Flow

```
┌─────────────────────┐
│ Authentication      │
│ successful          │
└─────────┬───────────┘
          │
          ▼
┌─────────────────────┐
│ nlMethodSelected    │
│ event dispatched    │
└─────────┬───────────┘
          │
          ▼
┌─────────────────────┐    Extension?    ┌─────────────────────┐
│ AuthManager.        │─────────────────▶│ Store verification  │
│ saveAuthState()     │                  │ data only (no       │
└─────────┬───────────┘                  │ secrets)            │
          │ Local Key?                   └─────────────────────┘
          ▼
┌─────────────────────┐
│ Encrypt secret key  │
│ with session        │
│ password + AES-GCM  │
└─────────┬───────────┘
          │ NIP-46?
          ▼
┌─────────────────────┐
│ Store connection    │
│ parameters (no      │
│ secrets)            │
└─────────┬───────────┘
          │ Read-only?
          ▼
┌─────────────────────┐
│ Store method only   │
│ (no secrets)        │
└─────────┬───────────┘
          │
          ▼
┌─────────────────────┐    isolateSession?   ┌─────────────────────┐
│ Choose storage:     │─────────YES─────────▶│ sessionStorage      │
│ localStorage vs     │                      │ (per-window)        │
│ sessionStorage      │◀────────NO───────────┤                     │
└─────────┬───────────┘                      └─────────────────────┘
          │
          ▼
┌─────────────────────┐
│ localStorage        │
│ (cross-window)      │
└─────────────────────┘
```

## Key Decision Points and Logic

### 1. Extension Detection Logic (Line 994-1046)

**Function:** `NostrLite._isRealExtension(obj)`

```javascript
// Conservative extension detection
if (!obj || typeof obj !== 'object') return false;
if (typeof obj.getPublicKey !== 'function' || typeof obj.signEvent !== 'function') return false;

// Exclude our own classes
const constructorName = obj.constructor?.name;
if (constructorName === 'WindowNostr' || constructorName === 'NostrLite') return false;
if (obj === window.NostrTools) return false;

// Look for extension indicators
const extensionIndicators = [
  '_isEnabled', 'enabled', 'kind', '_eventEmitter', '_scope',
  '_requests', '_pubkey', 'name', 'version', 'description'
];
const hasIndicators = extensionIndicators.some(prop => obj.hasOwnProperty(prop));
const hasExtensionConstructor = constructorName && 
                               constructorName !== 'Object' && 
                               constructorName !== 'Function';

return hasIndicators || hasExtensionConstructor;
```

### 2. Facade Installation Decision (Line 942-972)

**Function:** `NostrLite._setupWindowNostrFacade()`

```
Extension detected? ──YES──▶ DON'T install facade
                            Store reference for persistence
       │
       NO
       ▼
Install WindowNostr facade ──▶ Handle local/NIP-46/readonly methods
```

### 3. FloatingTab Click Behavior (Line 351-369)

**Current UX Inconsistency Issue:**

```javascript
async _handleClick() {
  if (this.isAuthenticated && this.options.behavior.showUserInfo) {
    this._showUserMenu(); // Show user options
  } else {
    // INCONSISTENCY: Auto-tries extension instead of opening modal
    if (window.nostr && this._isRealExtension(window.nostr)) {
      await this._tryExtensionLogin(window.nostr); // Automatic extension attempt
    } else {
      if (this.modal) {
        this.modal.open({ startScreen: 'login' }); // Fallback to modal
      }
    }
  }
}
```

**Comparison with Login Button behavior:**
- Login Button: **Always** opens modal for user choice
- FloatingTab: **Auto-tries extension first**, only shows modal if denied

### 4. Authentication Restoration on Page Refresh

**Two-Path System:**

#### Path 1: Extension Mode (Line 1115-1173)
```javascript
async _attemptExtensionRestore() {
  const authManager = new AuthManager({ isolateSession: this.options?.isolateSession });
  const storedAuth = await authManager.restoreAuthState();
  
  if (!storedAuth || storedAuth.method !== 'extension') return null;
  
  // Verify extension still works with same pubkey
  if (!window.nostr || !this._isRealExtension(window.nostr)) return null;
  
  const currentPubkey = await window.nostr.getPublicKey();
  if (currentPubkey !== storedAuth.pubkey) return null;
  
  // Dispatch nlAuthRestored event for UI updates
  window.dispatchEvent(new CustomEvent('nlAuthRestored', { detail: extensionAuth }));
}
```

#### Path 2: Non-Extension Mode (Line 1080-1098)  
```javascript
// Uses facade's restoreAuthState method
if (this.facadeInstalled && window.nostr?.restoreAuthState) {
  const restoredAuth = await window.nostr.restoreAuthState();
  
  if (restoredAuth) {
    // Handle NIP-46 reconnection if needed
    if (restoredAuth.requiresReconnection) {
      this._showReconnectionPrompt(restoredAuth);
    }
  }
}
```

### 5. Storage Strategy (Line 1408-1414)

**Storage Type Selection:**
```javascript
if (options.isolateSession) {
  this.storage = sessionStorage; // Per-window isolation
} else {
  this.storage = localStorage;   // Cross-window persistence
}
```

### 6. Event-Driven State Synchronization

**Key Events:**
- `nlMethodSelected` - Dispatched when user completes authentication
- `nlAuthRestored` - Dispatched when authentication is restored from storage
- `nlLogout` - Dispatched when user logs out
- `nlReconnectionRequired` - Dispatched when NIP-46 needs reconnection

**Event Listeners:**
- FloatingTab listens to all auth events for UI updates (Line 271-295)
- WindowNostr listens to nlMethodSelected/nlLogout for state management (Line 823-869)

## State Persistence Security Model

### By Authentication Method:

**Extension:**
- ✅ Store: pubkey, verification metadata
- ❌ Never store: extension object, secrets
- 🔒 Security: Minimal data, 1-hour expiry

**Local Key:**
- ✅ Store: encrypted secret key, pubkey
- 🔒 Security: AES-GCM encryption with session-specific password
- 🔑 Session password stored in sessionStorage (cleared on tab close)

**NIP-46:**
- ✅ Store: connection parameters, pubkey
- ❌ Never store: session secrets
- 🔄 Requires: User reconnection on restore

**Read-only:**
- ✅ Store: method type, pubkey
- ❌ No secrets to store

## Current Issues Identified

### UX Inconsistency (THE MAIN ISSUE)
**Problem:** FloatingTab and Login Button have different click behaviors
- **FloatingTab:** Auto-tries extension → Falls back to modal if denied
- **Login Button:** Always opens modal for user choice

**Impact:** 
- Confusing user experience
- Inconsistent interaction patterns
- Users don't get consistent choice of authentication method

**Root Cause:** Line 358-367 in FloatingTab._handleClick() method

### Proposed Solutions:

#### Option 1: Make FloatingTab Consistent (Recommended)
```javascript
async _handleClick() {
  if (this.isAuthenticated && this.options.behavior.showUserInfo) {
    this._showUserMenu();
  } else {
    // Always open modal - consistent with login button
    if (this.modal) {
      this.modal.open({ startScreen: 'login' });
    }
  }
}
```

#### Option 2: Add Configuration Option
```javascript
floatingTab: {
  behavior: {
    autoTryExtension: false, // Default to consistent behavior
    // ... other options
  }
}
```

## ⚠️ IMPLEMENTATION STATUS: READY FOR CODE CHANGES

**User Decision:** FloatingTab should behave exactly like login buttons - always open modal for authentication method selection.

**Required Changes:**
1. **File:** `lite/build.js`
2. **Method:** `FloatingTab._handleClick()` (lines 351-369)
3. **Action:** Remove extension auto-detection, always open modal

**Current Code to Replace (lines 358-367):**
```javascript
// Check if extension is available for direct login
if (window.nostr && this._isRealExtension(window.nostr)) {
  console.log('FloatingTab: Extension available, attempting direct extension login');
  await this._tryExtensionLogin(window.nostr);
} else {
  // Open login modal
  if (this.modal) {
    this.modal.open({ startScreen: 'login' });
  }
}
```

**Replacement Code:**
```javascript
// Always open login modal (consistent with login buttons)
if (this.modal) {
  this.modal.open({ startScreen: 'login' });
}
```

**Critical Safety Notes:**
- ✅ **DO NOT** change `_checkExistingAuth()` method (lines 299-349) - this handles automatic restoration on page refresh
- ✅ **ONLY** change the click handler to remove manual extension detection
- ✅ Authentication restoration will continue to work properly via the separate restoration system
- ✅ Extension detection logic remains intact for other purposes (storage, verification, etc.)

**After Implementation:**
- Rebuild the library with `node lite/build.js`
- Test that both floating tab and login buttons behave identically
- Verify that automatic login restoration on page refresh still works properly

## Important Notes

1. **Extension-First Architecture:** The system never interferes with real browser extensions
2. **Dual Storage Support:** Supports both per-window (sessionStorage) and cross-window (localStorage) persistence
3. **Security-First:** Sensitive data is always encrypted or not stored
4. **Event-Driven:** All components communicate via custom events
5. **Automatic Restoration:** Authentication state is automatically restored on page refresh when possible

The login logic is complex due to supporting multiple authentication methods, security requirements, and different storage strategies, but it provides a flexible and secure authentication system for Nostr applications.