7. User Experience7.2 Session Ephemeral Keys

7.2. Session Ephemeral Keys

Session Ephemeral Keys are the cryptographic backbone of Fhenix-FairMarket’s frictionless user experience. Traditional Web3 applications require users to sign a wallet prompt for every discrete action, creating friction and exposing sensitive signing permits to browser-based Cross-Site Scripting (XSS) attacks.

Version 2.0 resolves this by integrating ERC-4337 Account Abstraction. Upon initial authentication, the protocol generates a temporary, cryptographically scoped signing permit with a strict 24-hour Time-To-Live (TTL). These keys enable seamless 1-Click Trade interactions—locking escrow, submitting encrypted bids, and claiming refunds—without repeated Metamask pop-ups, while maintaining rigorous security through memory-isolated storage and granular permission boundaries.

Core Design Principles

PrincipleTechnical Implementation
24-Hour TTLSession keys are cryptographically bound to a strict expiry window. After 24 hours, the permit becomes mathematically invalid, limiting the attack surface.
Scoped PermissionsKeys are restricted to auction-specific functions only: placeBid(), lockEscrow(), and claimRefund(). They cannot approve arbitrary token transfers, upgrade contracts, or interact with external protocols.
Memory-Only StoragePermits are stored in secure application memory or encrypted IndexedDB via the Web Crypto API. localStorage and cookies are strictly prohibited to neutralize XSS theft vectors.
Fail-Safe FallbackIf a session expires or the Smart Account fails, the UI automatically reverts to standard wallet signing without losing form state or draft inputs.
Device-Agnostic GenerationKeys are derived locally in the browser session. No server-side generation or cloud-synced secrets, ensuring zero backend leakage.

️ Technical Implementation

1. Session Key Lifecycle Hook (useERC4337Session.ts)

Manages creation, validation, encryption, and automatic expiration of the ephemeral permit.

// packages/frontend/src/lib/hooks/useERC4337Session.ts
import { useState, useEffect, useCallback } from 'react';
import { createSmartAccountClient } from 'permissionless';
import { encryptWithWebCrypto, storeInIndexedDB, readFromIndexedDB } from '@lib/crypto';
 
export function useERC4337Session() {
 const [session, setSession] = useState<SessionPermit | null>(null);
 
 // 1. Create Ephemeral Session Key (One-time user signature required)
 const createSession = async () => {
 const smartAccount = await createSmartAccountClient({ signer: window.ethereum });
 
 const permit = await smartAccount.createSessionKey({
 ttl: 24 * 60 * 60, // 24-hour strict TTL
 scope: ['placeBid', 'lockEscrow', 'claimRefund'], // Granular function binding
 });
 
 // Encrypt payload via Web Crypto API before IndexedDB persistence
 const encrypted = await encryptWithWebCrypto(permit);
 await storeInIndexedDB('ffm_session', encrypted);
 setSession(permit);
 };
 
 // 2. Load & Validate Existing Session
 useEffect(() => {
 const loadSession = async () => {
 const encrypted = await readFromIndexedDB('ffm_session');
 if (!encrypted) return;
 
 const permit = await decryptWithWebCrypto(encrypted);
 if (permit.expiresAt > Date.now()) {
 setSession(permit);
 } else {
 await clearSession(); // Auto-expire
 }
 };
 loadSession();
 }, []);
 
 // 3. Secure Cleanup
 const clearSession = useCallback(async () => {
 await window.indexedDB.deleteDatabase('ffm_session_db');
 setSession(null);
 }, []);
 
 return { session, createSession, clearSession, isSessionActive: !!session && session.expiresAt > Date.now() };
}

2. Strict Storage Enforcement (CI/CD Level)

To guarantee the “Memory-Only” principle, the project enforces a zero-tolerance policy for insecure browser storage at the build level.

// .eslintrc.js
{
 "rules": {
 "no-restricted-properties": [
 "error",
 { 
 "object": "localStorage", 
 "message": "Forbidden: Session keys must use encrypted IndexedDB or secure memory via Web Crypto API." 
 },
 { 
 "object": "document", 
 "property": "cookie", 
 "message": "Forbidden: No cookies allowed for cryptographic permits." 
 }
]
 }
}

3. Scoped Permission Validation

The permissionless SDK enforces permission boundaries at the UserOperation level. If a session key attempts to call upgradeToAndCall or transfer on an arbitrary address, the Bundler rejects it before it reaches the mempool.

Session Lifecycle & Security Flow

️ Security Guarantees & Threat Mitigations

Threat VectorMitigation Strategy
XSS Key TheftPermits are never stored in localStorage. They are AES-GCM encrypted via the Web Crypto API before persistence in IndexedDB, rendering them useless to injected scripts without the decryption key.
Session HijackingStrict 24-hour TTL ensures that even if a permit is intercepted, the attacker has a severely limited window to exploit it before the key cryptographically expires.
Unauthorized SpendingScoped Permissions restrict the session key to auction-specific functions. A compromised key cannot drain the user’s main wallet or interact with external DeFi protocols.
Replay AttacksEach UserOperation includes a unique nonce and paymasterData. The Bundler validates nonce monotonicity, preventing intercepted session signatures from being replayed.
Phishing / Signing BlindnessBy reducing signature prompts, users are less likely to blindly sign transactions. Critical state changes (like EmergencyHalt or contract upgrades) still require explicit main-wallet confirmation.

Audit Gate Compliance (P0)

Progression through Phase 5 is strictly blocked until all P0 items pass:

  • [] Zero localStorage/cookies usage: Enforced via ESLint no-restricted-properties rule and CI static analysis.
  • [] 24-Hour TTL Enforced: Session permits automatically invalidate post-expiry; UI prompts for re-authentication without state loss.
  • [] Granular Scoping: Keys cannot authorize upgradeToAndCall, approve(), or arbitrary fund transfers outside the defined auction scope.
  • [] Fail-Safe Fallback: UI correctly prompts for standard wallet signature upon session expiry, network drop, or Bundler failure.
  • [] Memory Encryption: All IndexedDB payloads are encrypted using Web Crypto API before persistence. Decryption occurs only in RAM during active use.
  • [] Nonce & Replay Protection: Each session-signed transaction includes a monotonically increasing nonce, validated by the Bundler before execution.

Unresolved Points & Explicit Gaps

Gap / Unresolved PointImpactCurrent StatusRecommended Action
Gas Sponsorship LogicWho pays L2 gas for session-key-signed bids? User’s Smart Account or protocol bundler?Docs imply user pays; explicit paymaster configuration not detailed in Phase 5.Integrate a verified Paymaster in createSmartAccountClient to subsidize gas for verified users, enhancing the true “1-Click” feel.
Offline Bidding QueueCan users encrypt and queue bids while offline for later broadcast?Not supported in current architecture.Implement a local queue mechanism via Service Workers to allow bid preparation during connectivity loss.
Device BindingIs the session key bound to a specific device fingerprint or Passkey?Currently bound only to browser storage.Consider adding device-bound attestation (e.g., WebAuthn/Passkeys) for higher security tiers in v2.1.
Session RevocationCan users manually revoke an active session before 24h expiry?Manual revocation logic not explicitly implemented in SessionKeyManager.Add a “Revoke Session” button that clears IndexedDB and broadcasts a revocation UserOperation to the Bundler.

Fact vs. Analysis Distinction: The 24-hour TTL, IndexedDB + Web Crypto encryption, scoped permissions, and ESLint enforcement are verified facts from the Phase 5 Matrix and Technical Specification. Gas sponsorship models, offline queuing, device binding, and manual revocation are unresolved architectural gaps requiring explicit definition before Mainnet launch.


Next Steps