Skip to content

JavaScript Architecture

Rain Zhang edited this page Nov 6, 2025 · 2 revisions

JavaScript Architecture

Table of Contents

  1. Introduction
  2. Architecture Overview
  3. Directory Structure
  4. Main Entry Point
  5. Authentication Flows
  6. Shared Utility Modules
  7. Advanced Features
  8. Integration Patterns
  9. Error Handling and Debugging
  10. Extending the Architecture
  11. Best Practices

Introduction

The JavaScript architecture of the post-quantum WebAuthn platform follows a modular, separation-of-concerns design pattern that organizes functionality across three main categories: simple authentication, advanced authentication, and shared utilities. The architecture is built around the WebAuthn API and provides comprehensive support for post-quantum cryptographic algorithms while maintaining a clean separation between authentication flows and shared functionality.

The frontend implementation demonstrates sophisticated module organization with clear boundaries between simple and advanced authentication scenarios, robust state management, and extensive utility functions for WebAuthn operations, binary data handling, and user interface management.

Architecture Overview

The JavaScript architecture is structured around a hierarchical module system that promotes reusability and maintainability:

graph TB
subgraph "Entry Point"
MainJS[main.js]
end
subgraph "Simple Authentication"
SimpleAuth[auth-simple.js]
SimpleForms[forms.js]
end
subgraph "Advanced Authentication"
AdvancedAuth[auth-advanced.js]
AdvancedForms[forms.js]
JsonEditor[json-editor.js]
CredentialDisplay[credential-display.js]
end
subgraph "Shared Utilities"
State[state.js]
Navigation[navigation.js]
LocalStorage[local-storage.js]
UI[ui.js]
BinaryUtils[binary-utils.js]
Status[status.js]
Loader[loader.js]
Username[username.js]
WebAuthnPonyfill[webauthn-json.browser-ponyfill.js]
CredentialArtifacts[credential-artifacts-client.js]
AuthDebug[auth-debug.js]
end
MainJS --> SimpleAuth
MainJS --> AdvancedAuth
MainJS --> State
MainJS --> Navigation
MainJS --> UI
MainJS --> Loader
SimpleAuth --> WebAuthnPonyfill
SimpleAuth --> LocalStorage
SimpleAuth --> Status
AdvancedAuth --> WebAuthnPonyfill
AdvancedAuth --> JsonEditor
AdvancedAuth --> CredentialDisplay
AdvancedAuth --> Forms
AdvancedAuth --> Status
JsonEditor --> BinaryUtils
JsonEditor --> CredentialDisplay
JsonEditor --> Forms
CredentialDisplay --> LocalStorage
CredentialDisplay --> CredentialArtifacts
CredentialDisplay --> BinaryUtils
Forms --> BinaryUtils
Forms --> Status
Forms --> Username
Loading

Diagram sources

  • main.js
  • auth-simple.js
  • auth-advanced.js

Directory Structure

The JavaScript modules are organized into three primary directories within the scripts/static/scripts folder:

Simple Directory (scripts/static/scripts/simple/)

Contains the basic authentication implementation:

  • auth-simple.js: Core authentication flow for simple scenarios
  • forms.js: Form validation and manipulation utilities

Advanced Directory (scripts/static/scripts/advanced/)

Contains sophisticated authentication features:

  • auth-advanced.js: Advanced authentication with WebAuthn extensions
  • forms.js: Enhanced form handling with validation
  • json-editor.js: JSON configuration editor
  • credential-display.js: Credential management and display
  • credential-utils.js: Credential utility functions
  • display-utils.js: UI display utilities
  • exclude-credentials.js: Credential exclusion management
  • hints.js: Authenticator hint processing
  • constants.js: Shared constants
  • mds.js: Metadata service integration
  • settings-nav.js: Settings navigation

Shared Directory (scripts/static/scripts/shared/)

Contains reusable utilities and state management:

  • state.js: Global application state
  • navigation.js: UI navigation and routing
  • local-storage.js: Persistent storage management
  • ui.js: User interface utilities
  • binary-utils.js: Binary data conversion
  • status.js: Status and progress indicators
  • loader.js: Application loading state
  • username.js: Username generation utilities
  • webauthn-json.browser-ponyfill.js: WebAuthn API compatibility
  • credential-artifacts-client.js: Credential artifact management
  • auth-debug.js: Debugging utilities

Section sources

  • main.js

Main Entry Point

The main.js file serves as the central orchestrator for the entire JavaScript architecture, establishing the foundation for all authentication flows and UI interactions.

Module Imports and Initialization

The main entry point imports and initializes all core modules:

sequenceDiagram
participant Browser as Browser
participant MainJS as main.js
participant State as state.js
participant Navigation as navigation.js
participant UI as ui.js
participant AuthSimple as auth-simple.js
participant AuthAdvanced as auth-advanced.js
Browser->>MainJS : DOMContentLoaded
MainJS->>State : Initialize global state
MainJS->>Navigation : Initialize navigation menu
MainJS->>UI : Initialize UI components
MainJS->>AuthSimple : Import simple auth functions
MainJS->>AuthAdvanced : Import advanced auth functions
MainJS->>MainJS : Expose global functions
MainJS->>Browser : Ready for user interaction
Loading

Diagram sources

  • main.js

Global Function Exposure

The main entry point exposes all public functions to the global window object, enabling seamless integration with Flask backend routes:

Function Category Functions Purpose
Authentication simpleRegister, simpleAuthenticate Basic authentication operations
Authentication advancedRegister, advancedAuthenticate Advanced authentication with extensions
Navigation switchTab, switchSubTab, toggleSection UI navigation and routing
UI Management showInfoPopup, hideInfoPopup, closeModal User interface interactions
Form Management randomizeChallenge, randomizeUserIdentity Form data manipulation
Credential Management loadSavedCredentials, showCredentialDetails Credential operations

Spellcheck Management

The architecture includes sophisticated spellcheck management to prevent browser interference with cryptographic data:

// Disable browser spellchecking globally (including dynamically added inputs)
const shouldDisableSpellcheck = (element) => {
    if (element instanceof HTMLTextAreaElement) {
        return true;
    }
    if (element instanceof HTMLInputElement) {
        return TEXT_INPUT_TYPES.has((element.type || 'text').toLowerCase());
    }
    if (!(element instanceof HTMLElement)) {
        return false;
    }
    if (element.isContentEditable) {
        return true;
    }
    return element.getAttribute('role') === 'textbox';
};

Section sources

  • main.js

Authentication Flows

The authentication architecture implements two distinct flows: simple and advanced, each serving different use cases and security requirements.

Simple Authentication Flow

The simple authentication flow provides streamlined WebAuthn operations with minimal configuration:

sequenceDiagram
participant User as User
participant UI as UI Layer
participant SimpleAuth as auth-simple.js
participant WebAuthn as WebAuthn API
participant Backend as Flask Backend
participant Storage as Local Storage
User->>UI : Enter email and click register/authenticate
UI->>SimpleAuth : Call simpleRegister/simpleAuthenticate
SimpleAuth->>Backend : POST /api/register/begin
Backend-->>SimpleAuth : Registration options
SimpleAuth->>WebAuthn : navigator.credentials.create/get
WebAuthn-->>SimpleAuth : Credential/Assertion
SimpleAuth->>Backend : POST /api/register/complete
Backend-->>SimpleAuth : Registration result
SimpleAuth->>Storage : Save credential locally
SimpleAuth-->>UI : Success/failure message
UI-->>User : Display result
Loading

Diagram sources

  • auth-simple.js

Simple Authentication Implementation

The simple authentication flow handles basic registration and authentication with automatic credential management:

// Registration flow example
export async function simpleRegister() {
    const email = document.getElementById('simple-email').value;
    if (!email) {
        showStatus('simple', 'Please enter a username.', 'error');
        return;
    }
    
    try {
        // Fetch registration options from backend
        const response = await fetch(`/api/register/begin?email=${encodeURIComponent(email)}`);
        
        // Parse and process WebAuthn options
        const json = await response.json();
        const createOptions = parseCreationOptionsFromJSON(optionsWithoutState);
        
        // Execute WebAuthn registration
        const credential = await create(createOptions);
        
        // Complete registration with backend
        const result = await fetch(`/api/register/complete?email=${encodeURIComponent(email)}`, {
            method: 'POST',
            body: JSON.stringify(credentialJson)
        });
        
        // Handle success and save credential
        if (result.ok) {
            const data = await result.json();
            saveSimpleCredential({ ...data.storedCredential, email });
            loadSavedCredentials();
        }
    } catch (error) {
        // Handle errors gracefully
        showStatus('simple', errorMessage, 'error');
    }
}

Advanced Authentication Flow

The advanced authentication flow supports complex WebAuthn configurations with extensive extension capabilities:

sequenceDiagram
participant User as User
participant UI as UI Layer
participant AdvancedAuth as auth-advanced.js
participant JsonEditor as json-editor.js
participant WebAuthn as WebAuthn API
participant Backend as Flask Backend
participant Storage as Local Storage
User->>UI : Configure advanced options
UI->>JsonEditor : Update JSON configuration
JsonEditor->>AdvancedAuth : Trigger validation
AdvancedAuth->>Backend : POST /api/advanced/register/begin
Backend-->>AdvancedAuth : Advanced options
AdvancedAuth->>WebAuthn : navigator.credentials.create/get
WebAuthn-->>AdvancedAuth : Credential/Assertion
AdvancedAuth->>Backend : POST /api/advanced/register/complete
Backend-->>AdvancedAuth : Extended result
AdvancedAuth->>Storage : Store with artifacts
AdvancedAuth-->>UI : Display detailed result
UI-->>User : Show registration details
Loading

Diagram sources

  • auth-advanced.js

Advanced Authentication Features

The advanced authentication flow supports:

Feature Description Implementation
JSON Configuration Full WebAuthn option customization Dynamic JSON editor with validation
Extension Support PRF, Large Blob, Cred Props extensions Automatic extension detection and processing
Credential Artifacts Persistent credential metadata Server-side artifact storage
Multi-algorithm Support Post-quantum and classical algorithms Algorithm selection and validation
Hint Processing Authenticator hint filtering Intelligent authenticator selection

Section sources

  • auth-simple.js
  • auth-advanced.js

Shared Utility Modules

The shared utility modules provide foundational functionality that supports both simple and advanced authentication flows.

State Management (state.js)

The global state management system maintains application-wide data:

export const state = {
    currentSubTab: 'registration',
    storedCredentials: [],
    currentJsonMode: null,
    currentJsonData: null,
    lastFakeCredLength: 0,
    generatedExcludeCredentials: [],
    generatedAllowCredentials: [],
    utf8Decoder: typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8') : null,
};

Navigation System (navigation.js)

The navigation system handles UI routing and tab management:

flowchart TD
Start([User Interaction]) --> CheckViewport{Mobile Viewport?}
CheckViewport --> |Yes| MobileNav[Mobile Navigation]
CheckViewport --> |No| DesktopNav[Desktop Navigation]
MobileNav --> ToggleMenu[Toggle Menu]
DesktopNav --> TabSwitch[Switch Tab]
ToggleMenu --> UpdateState[Update Body Classes]
TabSwitch --> UpdateState
UpdateState --> HideAllMessages[Hide Transient Messages]
HideAllMessages --> ScrollReset[Reset Scroll Position]
ScrollReset --> DispatchEvent[Dispatch Tab Changed Event]
DispatchEvent --> End([Navigation Complete])
Loading

Diagram sources

  • navigation.js

Local Storage Management (local-storage.js)

The local storage system manages credential persistence with artifact synchronization:

classDiagram
class LocalStorageManager {
+saveSimpleCredential(credential)
+saveAdvancedCredential(credential)
+getAllStoredCredentialsInOrder()
+removeAdvancedCredential(id)
+ensureAdvancedCredentialArtifactsSynced()
-persistUnifiedCredentialRecords(records)
-synchroniseAdvancedCredentialArtifacts()
}
class CredentialArtifactsClient {
+fetchCredentialArtifact(storageId)
+uploadCredentialArtifact(storageId, artifact)
+updateCredentialSnapshot(storageId, snapshot)
+deleteCredentialArtifact(storageId)
}
class StorageConstants {
+SHARED_STORAGE_KEY : "postquantum-webauthn.credentials"
+LEGACY_SIMPLE_STORAGE_KEY : "postquantum-webauthn.simpleCredentials"
+LEGACY_ADVANCED_STORAGE_KEY : "postquantum-webauthn.advancedCredentials"
}
LocalStorageManager --> CredentialArtifactsClient : uses
LocalStorageManager --> StorageConstants : references
Loading

Diagram sources

  • local-storage.js
  • credential-artifacts-client.js

Binary Data Utilities (binary-utils.js)

The binary utilities provide comprehensive data conversion capabilities:

Function Category Purpose Examples
Hex Operations Hexadecimal data handling hexToBase64Url, base64UrlToHex, generateRandomHex
Base64 Encoding Base64 URL encoding base64ToBase64Url, base64UrlToUtf8String
Binary Conversion Type conversions bufferSourceToUint8Array, arrayBufferToHex
Extension Processing WebAuthn extension handling convertExtensionsForClient, normalizeClientExtensionResults

WebAuthn Compatibility (webauthn-json.browser-ponyfill.js)

The WebAuthn ponyfill ensures cross-browser compatibility:

// Core WebAuthn API wrapper
export async function create(options) {
    const response = await navigator.credentials.create(options);
    response.toJSON = () => createResponseToJSON(response);
    return response;
}

export async function get(options) {
    const response = await navigator.credentials.get(options);
    response.toJSON = () => getResponseToJSON(response);
    return response;
}

Section sources

  • state.js
  • navigation.js
  • local-storage.js
  • binary-utils.js
  • webauthn-json.browser-ponyfill.js

Advanced Features

The advanced authentication system provides sophisticated features for complex WebAuthn scenarios.

JSON Editor System

The JSON editor enables dynamic WebAuthn configuration:

flowchart TD
UserInput[User Input] --> Validation[JSON Validation]
Validation --> SchemaCheck{Valid Schema?}
SchemaCheck --> |No| ErrorDisplay[Display Error]
SchemaCheck --> |Yes| MergeLogic[Merge with Current Config]
MergeLogic --> KnownKeys[Validate Known Keys]
KnownKeys --> UnknownKeys[Handle Unknown Keys]
UnknownKeys --> PruneUnsupported[Prune Unsupported Properties]
PruneUnsupported --> RenderOutput[Render JSON Output]
ErrorDisplay --> UserInput
RenderOutput --> ApplyChanges[Apply Changes]
ApplyChanges --> UpdateForm[Update Form Fields]
UpdateForm --> TriggerValidation[Trigger Validation]
Loading

Diagram sources

  • json-editor.js

Credential Management

The credential management system handles complex credential lifecycle operations:

sequenceDiagram
participant UI as UI Layer
participant CredentialDisplay as credential-display.js
participant LocalStorage as local-storage.js
participant ArtifactClient as credential-artifacts-client.js
participant Backend as Flask Backend
UI->>CredentialDisplay : Load saved credentials
CredentialDisplay->>LocalStorage : getAllStoredCredentialsInOrder()
LocalStorage-->>CredentialDisplay : Credential list
loop For each credential
CredentialDisplay->>ArtifactClient : fetchCredentialArtifact(storageId)
ArtifactClient->>Backend : GET /api/advanced/credential-artifacts/{id}
Backend-->>ArtifactClient : Credential artifact
ArtifactClient-->>CredentialDisplay : Hydrated credential
end
CredentialDisplay-->>UI : Display credential list
Loading

Diagram sources

  • credential-display.js

Form Validation System

The form validation system provides comprehensive input validation:

Validation Type Scope Implementation
Hex Validation Binary inputs Format detection and length validation
Challenge Validation Authentication challenges Minimum length requirements
Algorithm Validation Signature algorithms Supported algorithm checking
Extension Validation WebAuthn extensions Capability detection and validation

Section sources

  • json-editor.js
  • credential-display.js
  • forms.js

Integration Patterns

The JavaScript architecture demonstrates several key integration patterns that enable seamless communication between frontend and backend systems.

Flask Backend Integration

The frontend integrates with Flask backend routes through standardized HTTP APIs:

sequenceDiagram
participant Frontend as JavaScript Frontend
participant Flask as Flask Backend
participant Database as Database
participant WebAuthn as WebAuthn Service
Frontend->>Flask : POST /api/register/begin
Flask->>Database : Check user existence
Database-->>Flask : User status
Flask->>WebAuthn : Generate challenge
WebAuthn-->>Flask : Registration options
Flask-->>Frontend : JSON registration options
Frontend->>Flask : POST /api/register/complete
Flask->>WebAuthn : Verify credential
WebAuthn-->>Flask : Verification result
Flask->>Database : Store credential
Database-->>Flask : Confirmation
Flask-->>Frontend : Registration success
Loading

Error Handling Patterns

The architecture implements comprehensive error handling across all modules:

// Consistent error handling pattern
try {
    // WebAuthn operation
    const result = await fetch('/api/endpoint', {
        method: 'POST',
        body: JSON.stringify(data)
    });
    
    if (!result.ok) {
        const errorText = await result.text();
        throw new Error(`Server error: ${errorText}`);
    }
    
    return await result.json();
} catch (error) {
    // Graceful error handling
    let errorMessage = error.message;
    if (error.name === 'NotAllowedError') {
        errorMessage = 'User cancelled or authenticator not available';
    }
    showStatus('tab', errorMessage, 'error');
}

Asynchronous Operation Management

The architecture manages complex asynchronous operations with proper state handling:

flowchart TD
AsyncOperation[Async Operation] --> ShowProgress[Show Progress Indicator]
ShowProgress --> ExecuteOperation[Execute Operation]
ExecuteOperation --> CheckResult{Operation Successful?}
CheckResult --> |Yes| ProcessResult[Process Result]
CheckResult --> |No| HandleError[Handle Error]
ProcessResult --> UpdateUI[Update UI]
HandleError --> ShowError[Show Error Message]
UpdateUI --> HideProgress[Hide Progress Indicator]
ShowError --> HideProgress
HideProgress --> CleanupState[Cleanup State]
CleanupState --> End([Operation Complete])
Loading

Section sources

  • auth-simple.js
  • auth-advanced.js

Error Handling and Debugging

The architecture provides comprehensive error handling and debugging capabilities.

Error Classification System

The error handling system categorizes errors by type and provides appropriate user feedback:

Error Category WebAuthn Error User Message Recovery Action
User Cancellation NotAllowedError "User cancelled or authenticator not available" Retry operation
Authentication Issue InvalidStateError "Authenticator is already registered for this account" Check existing credentials
Security Error SecurityError "Security error - check your connection and try again" Verify network connection
Browser Support NotSupportedError "WebAuthn is not supported in this browser" Use supported browser

Debugging Utilities (auth-debug.js)

The debugging system provides detailed logging for development and troubleshooting:

// Registration debug output
export function printRegistrationDebug(credential, createOptions, serverResponse) {
    const clientExtensions = credential.getClientExtensionResults
        ? credential.getClientExtensionResults()
        : (credential.clientExtensionResults || {});
    
    console.log('Resident key:', residentKey);
    console.log('Attestation (retrieve or not, plus the format):', `${attestationRetrieved}, ${attestationFormat}`);
    console.log('exclude credentials:', excludeCredentials);
    console.log('challenge hex code:', challengeHex);
    console.log('pubkeycredparam used:', pubKeyCredParams);
    console.log('hints:', hints);
    console.log('credprotect setting:', credProtectDisplay);
    console.log('largeblob:', largeBlob);
    console.log('prf:', prfEnabled);
}

Status and Progress Management

The status system provides real-time feedback during operations:

stateDiagram-v2
[*] --> Hidden
Hidden --> Showing : showStatus()
Showing --> Visible : Animation
Visible --> Dismissed : Auto-hide (10s)
Showing --> Dismissed : hideStatus()
Dismissed --> Hidden : Reset
[*] --> HiddenProgress
HiddenProgress --> ShowingProgress : showProgress()
ShowingProgress --> VisibleProgress : Display
VisibleProgress --> HiddenProgress : hideProgress()
Loading

Diagram sources

  • status.js

Section sources

  • auth-debug.js
  • status.js

Extending the Architecture

The modular architecture supports extension through well-defined interfaces and patterns.

Adding New Authentication Features

To add new authentication features, follow the established patterns:

  1. Create Feature Module: Add new functionality to appropriate directory
  2. Extend State Management: Update state.js with new state properties
  3. Integrate with Navigation: Add navigation handlers if needed
  4. Add UI Components: Create corresponding UI elements
  5. Update Backend Integration: Extend Flask routes as needed

Supporting New WebAuthn Extensions

The architecture supports adding new WebAuthn extensions through the extension processing system:

// Example extension processing pattern
export function convertExtensionsForClient(extensionsJson) {
    if (!extensionsJson || typeof extensionsJson !== 'object') {
        return undefined;
    }
    
    const converted = {};
    
    Object.entries(extensionsJson).forEach(([name, value]) => {
        switch (name) {
            case 'newExtension':
                converted.newExtension = processNewExtension(value);
                break;
            // ... other extensions
        }
    });
    
    return Object.keys(converted).length > 0 ? converted : undefined;
}

Customizing Authentication Flows

The authentication flows can be customized by extending the base functionality:

// Custom authentication flow extension
export async function customRegister() {
    // Pre-processing
    await preprocessCustomRequirements();
    
    // Standard registration flow
    const result = await simpleRegister();
    
    // Post-processing
    await postprocessCustomResults(result);
    
    return result;
}

Best Practices

The architecture demonstrates several JavaScript best practices that contribute to maintainability and reliability.

Modular Design Principles

  1. Single Responsibility: Each module has a clear, focused purpose
  2. Loose Coupling: Modules communicate through well-defined interfaces
  3. High Cohesion: Related functionality is grouped within modules
  4. Separation of Concerns: Authentication logic is separated from UI logic

Code Organization Patterns

// Consistent export/import pattern
import { create, get } from './webauthn-json.browser-ponyfill.js';
import { showStatus, hideStatus } from './status.js';

export async function advancedRegister() {
    // Implementation
}

// Clear function naming and documentation
/**
 * Performs advanced registration with WebAuthn extensions
 * @returns {Promise<Object>} Registration result
 */
export async function advancedRegister() {
    // Implementation
}

Error Handling Best Practices

  1. Graceful Degradation: Provide fallbacks for unsupported features
  2. User-Friendly Messages: Convert technical errors to understandable messages
  3. Consistent Logging: Use structured logging for debugging
  4. Recovery Mechanisms: Provide clear paths for error recovery

Performance Optimization

  1. Lazy Loading: Load modules only when needed
  2. Efficient State Management: Minimize unnecessary state updates
  3. Memory Management: Properly clean up event listeners and timers
  4. Optimized Rendering: Use efficient DOM manipulation techniques

Security Considerations

  1. Input Validation: Validate all user inputs and API responses
  2. Secure Storage: Use appropriate storage mechanisms for sensitive data
  3. Error Information: Avoid exposing sensitive information in error messages
  4. Cross-Site Scripting: Sanitize all user-generated content

The JavaScript architecture successfully demonstrates a sophisticated, maintainable approach to WebAuthn implementation that balances simplicity for basic use cases with powerful capabilities for advanced scenarios. The modular design, comprehensive error handling, and robust integration patterns provide a solid foundation for future enhancements and extensions.

Post-Quantum WebAuthn Platform

Getting Started

Architectural Foundations

Cryptography & Security

Authentication Platform

Core Protocol

Flows & Interfaces

Authenticator Capabilities

Server Platform

Frontend Platform

Architecture

Interaction & Utilities

Metadata Service (MDS)

Storage & Data Management

Data Models & Encoding

API Reference

Cross-Platform & HID

Operations & Troubleshooting

Glossary & References

Clone this wiki locally