Skip to content

UI Components

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

UI Components

Table of Contents

  1. Introduction
  2. Credential Display Component
  3. JSON Editor Implementation
  4. MDS Browser Functionality
  5. Settings Navigation Component
  6. Decoder/Encoder Interface
  7. Component Integration Patterns
  8. Performance Considerations
  9. Accessibility Features
  10. Troubleshooting Guide

Introduction

The PostQuantum WebAuthn Platform provides a comprehensive suite of UI components designed for advanced credential management, data visualization, and cryptographic operations. These components work together to create an intuitive interface for developers working with WebAuthn protocols, particularly focusing on post-quantum cryptography implementations.

The UI components are built with modern JavaScript ES6+ features, responsive design principles, and accessibility standards. They provide sophisticated data manipulation capabilities, real-time validation, and seamless integration with backend services for credential storage and metadata management.

Credential Display Component

The credential display component serves as the central hub for visualizing and managing WebAuthn credentials with comprehensive attestation information and metadata integration.

Architecture Overview

classDiagram
class CredentialDisplay {
+state : Object
+registrationDetailState : Object
+globalCursorApplyCount : Number
+applyGlobalCursor(cursorStyle) Function
+hydrateCredentialFromServer(cred) Promise
+deriveCredentialStatusIndicators(cred) Object
+composeRegistrationDetailHtml(options) Object
+updateCredentialsDisplay() void
+navigateToMdsAuthenticator(aaguid) Promise
}
class RegistrationDetailState {
+attestationObject : Object
+attestationCertificates : Array
+visibleAttestationCertificateIndices : Array
+authenticatorData : Object
+authenticatorDataHash : String
+authenticatorDataHex : String
}
class CredentialStatusIndicators {
+signatureStatus : Boolean
+rootStatus : Boolean
+rpidStatus : Boolean
+aaguidStatus : Boolean
+metadataAvailable : Boolean
+aaguidGuid : String
}
CredentialDisplay --> RegistrationDetailState : "manages"
CredentialDisplay --> CredentialStatusIndicators : "generates"
Loading

Diagram sources

  • credential-display.js

Core Functionality

The credential display component provides several key capabilities:

Global Cursor Management

The component implements sophisticated cursor management for user feedback during long-running operations:

// Example usage pattern for global cursor management
const restoreCursor = applyGlobalCursor('progress');
try {
    await hydrateCredentialFromServer(cred);
} finally {
    restoreCursor();
}

Credential Status Indicators

Each credential displays comprehensive status information including:

  • Signature validation status
  • Root certificate validation
  • RPID hash verification
  • AAGUID matching status
  • Metadata availability

Dynamic Content Generation

The component dynamically generates HTML content for credential details, including:

  • Authenticator response data
  • Parsed client data JSON
  • Relying party information
  • Attestation object details
  • Certificate chain information

Section sources

  • credential-display.js
  • credential-display.js

Filtering and Exclusion Features

The credential display integrates with the exclude credentials functionality to support advanced filtering scenarios:

Fake Credential Management

The system supports creation and management of fake credential IDs for testing:

// Create fake credentials for testing
const fakeCredential = createFakeCredential('exclude', 32); // 32-byte credential
setFakeCredentials('allow', ['fake-credential-id-hex']);

Advanced Filtering Options

Credentials can be filtered based on:

  • Algorithm type (PQC vs traditional)
  • Authenticator attachment type
  • Resident key capability
  • Large blob support
  • Custom metadata filters

Section sources

  • credential-display.js
  • exclude-credentials.js

JSON Editor Implementation

The JSON editor provides sophisticated structured data manipulation capabilities with syntax highlighting, validation, and intelligent formatting.

Editor Architecture

classDiagram
class JsonEditor {
+state : Object
+KNOWN_REGISTRATION_PUBLIC_KEY_KEYS : Set
+KNOWN_AUTHENTICATION_PUBLIC_KEY_KEYS : Set
+validateRegistrationPublicKey(publicKey) void
+validateAuthenticationPublicKey(publicKey) void
+mergePublicKey(existing, latest, scope) Object
+pruneUnsupportedProperties(merged, scope) void
+buildOptionsForCurrentScope(scope) Object
}
class JsonEditorUtils {
+wrapSelectionWithPair(editor, opening, closing) void
+applyJsonEditorAutoIndent(editor) void
+applyTabIndentation(editor, isShift) void
+handleJsonEditorKeydown(event) void
}
class ValidationRules {
+KNOWN_RP_KEYS : Set
+KNOWN_USER_KEYS : Set
+KNOWN_AUTH_SELECTION_KEYS : Set
+KNOWN_REGISTRATION_EXTENSION_KEYS : Set
+KNOWN_AUTHENTICATION_EXTENSION_KEYS : Set
}
JsonEditor --> JsonEditorUtils : "uses"
JsonEditor --> ValidationRules : "validates against"
Loading

Diagram sources

  • json-editor.js
  • json-editor-utils.js

Validation System

The JSON editor implements comprehensive validation rules for WebAuthn operations:

Registration Validation

// Example validation for registration public key
validateRegistrationPublicKey({
    rp: { name: 'Test RP', id: 'example.com' },
    user: { id: 'user-id', name: 'Test User', displayName: 'Test User' },
    challenge: 'challenge-data',
    pubKeyCredParams: [{ type: 'public-key', alg: -7 }],
    authenticatorSelection: {
        authenticatorAttachment: 'cross-platform',
        residentKey: 'discouraged',
        userVerification: 'preferred'
    }
});

Authentication Validation

Similar validation applies to authentication requests with appropriate field restrictions.

Intelligent Merging

The editor intelligently merges existing configurations with new data while preserving unknown properties:

// Merge existing options with new data
const mergedOptions = mergePublicKey(
    existingPublicKey, 
    latestPublicKey, 
    'registration'
);
pruneUnsupportedProperties(mergedOptions, 'registration');

Section sources

  • json-editor.js
  • json-editor.js

Syntax Highlighting and Formatting

The editor provides advanced text editing capabilities:

Auto-indentation

Automatic indentation based on JSON structure:

  • Opening braces { and arrays [ trigger auto-indentation
  • Closing braces handle proper dedentation
  • Smart line wrapping maintains readability

Keyboard Shortcuts

  • Tab key for indentation/de-indentation
  • Enter key for automatic brace completion
  • Ctrl/Cmd combinations for advanced editing

Selection Handling

Intelligent selection wrapping for common JSON patterns:

// Wraps selected text with brackets or quotes
wrapSelectionWithPair(editor, '{', '}');

Section sources

  • json-editor-utils.js

MDS Browser Functionality

The Metadata Service (MDS) browser provides efficient navigation and search capabilities for authenticator metadata with advanced lazy-loading and filtering systems.

MDS Architecture

classDiagram
class MdsBrowser {
+mdsState : Object
+mdsData : Array
+filteredData : Array
+isLoading : Boolean
+hasLoaded : Boolean
+initializeMdsBrowser() void
+filterMdsData(filters) Array
+navigateToMdsAuthenticator(aaguid) Promise
}
class MdsLazyLoader {
+allEntries : Array
+fullyParsedIndices : Set
+fullyParsedKeys : Map
+isBackgroundLoading : Boolean
+startBackgroundLoading(options) Promise
+getRawEntryByIndex(index) Object
+findEntriesWithCertificate(certificate) Array
}
class FilterDropdown {
+input : Element
+onSelect : Function
+options : Array
+filtered : Array
+activeIndex : Number
+open() void
+close() void
+filter(query) void
+render() void
}
MdsBrowser --> MdsLazyLoader : "uses"
MdsBrowser --> FilterDropdown : "creates"
MdsLazyLoader --> FilterDropdown : "integrates with"
Loading

Diagram sources

  • mds.js
  • mds-lazy-loader.js
  • mds-dropdown.js

Lazy Loading System

The MDS browser implements sophisticated lazy loading to handle large metadata datasets efficiently:

Background Processing

// Start background loading with progress tracking
await startBackgroundLoading({
    onBatchProcessed: (batchIndices) => {
        // Process batch of entries
        processMdsEntries(batchIndices);
    }
});

Memory Management

  • Progressive parsing of metadata entries
  • Automatic cleanup of unused data
  • Efficient caching of frequently accessed entries
  • Configurable batch sizes for optimal performance

Certificate Search

Advanced certificate-based searching:

// Find entries containing specific certificates
const matchingEntries = findEntriesWithCertificate(certificateBase64);

Section sources

  • mds-lazy-loader.js

Filter Dropdown System

The filter dropdown provides intuitive search and selection capabilities:

Interactive Filtering

// Create filter dropdown with custom configuration
const dropdown = createFilterDropdown(inputElement, (value) => {
    applyMdsFilter(value);
}, { expandDropdown: true });

Keyboard Navigation

  • Arrow keys for navigation
  • Enter key for selection
  • Escape key for dismissal
  • Focus management for accessibility

Dynamic Options

Real-time option updates based on current dataset:

dropdown.setOptions(['Option 1', 'Option 2', 'Option 3']);

Section sources

  • mds-dropdown.js

Metadata Navigation

Seamless navigation to authenticator metadata with status feedback:

AAGUID Resolution

// Navigate to authenticator metadata by AAGUID
const navigationResult = await navigateToMdsAuthenticator(aaguid);
if (navigationResult.highlighted) {
    // Metadata found and highlighted
}

Status Integration

Real-time status updates during navigation:

  • Loading indicators
  • Success/failure notifications
  • Progress tracking

Section sources

  • mds.js

Settings Navigation Component

The settings navigation component provides responsive, scroll-based navigation for advanced configuration panels with intersection observer integration.

Navigation Architecture

classDiagram
class SettingsNav {
+state : Object
+navItems : Array
+observer : IntersectionObserver
+activeTarget : String
+initializeAdvancedSettingsNavigation() void
+observeSections() void
+setActive(targetId) void
}
class IntersectionObserver {
+root : Element
+rootMargin : String
+threshold : Array
+callback : Function
+disconnect() void
+observe(target) void
}
class NavItem {
+element : Element
+targetId : String
+scrollTarget : String
+addEventListener(type, handler) void
}
SettingsNav --> IntersectionObserver : "uses"
SettingsNav --> NavItem : "manages"
IntersectionObserver --> NavItem : "observes"
Loading

Diagram sources

  • settings-nav.js

Responsive Navigation

The settings navigation adapts to different screen sizes and content layouts:

Scroll-Based Activation

// Initialize responsive navigation
initializeAdvancedSettingsNavigation();

// Automatically tracks visible sections
// Updates active state based on viewport position

Intersection Observer Integration

Sophisticated viewport monitoring:

const observer = new IntersectionObserver((entries) => {
    const visible = entries
        .filter(entry => entry.isIntersecting)
        .sort((a, b) => a.boundingClientRect.top - b.boundingClientRect.top);
    
    if (visible.length > 0) {
        const topEntry = visible[0];
        setActive(topEntry.target.id);
    }
}, observerOptions);

Smooth Scrolling

Enhanced user experience with smooth scrolling:

// Scroll to target with smooth behavior
targetElement.scrollIntoView({ 
    behavior: 'smooth', 
    block: 'start' 
});

Section sources

  • settings-nav.js

Dynamic Section Management

The component automatically manages navigation items based on content availability:

Automatic Discovery

// Automatically discovers and observes sections
function observeSections() {
    navItems.forEach(item => {
        const targetId = getTargetId(item);
        if (targetId) {
            const sentinel = document.getElementById(targetId);
            if (sentinel) {
                observer.observe(sentinel);
            }
        }
    });
}

Event-Driven Updates

Responsive to dynamic content changes:

  • Tab switching events
  • Content loading events
  • Window resize events

Section sources

  • settings-nav.js

Decoder/Encoder Interface

The codec component provides comprehensive CBOR/JSON conversion capabilities with syntax highlighting and validation for WebAuthn payloads.

Codec Architecture

classDiagram
class Codec {
+currentCodecMode : String
+MODE_CONFIG : Object
+processCodec(mode) Promise
+switchCodecMode(mode) void
+clearCodec(mode) void
+toggleRawCodec(mode) void
}
class DecodedResult {
+success : Boolean
+type : String
+data : Object
+malformed : Array
+renderDecodedResult(container, payload, mode) void
}
class FormatConverter {
+convertFormat(value, from, to) String
+getCurrentBinaryFormat() String
+currentFormatToJsonFormat(value) Object
}
Codec --> DecodedResult : "produces"
Codec --> FormatConverter : "uses"
DecodedResult --> FormatConverter : "utilizes"
Loading

Diagram sources

  • codec.js

Supported Formats

The codec supports multiple input/output formats for comprehensive WebAuthn payload handling:

Input Formats

  • JSON: Standard JSON payloads
  • JSON (Binary): Binary-encoded JSON
  • CBOR: Canonical and CTAP/WebAuthn formats
  • Binary: Raw binary data
  • PEM: X.509 certificates
  • DER: DER-encoded certificates

Output Formats

  • CBOR: Canonical and CTAP/WebAuthn formats
  • JSON: Formatted JSON output
  • DER: DER-encoded output
  • PEM: PEM-encoded output
  • COSE: COSE format output

Processing Pipeline

flowchart TD
Input["User Input"] --> Validation["Format Validation"]
Validation --> Processing["Backend Processing"]
Processing --> Success{"Processing<br/>Successful?"}
Success --> |Yes| Rendering["Render Results"]
Success --> |No| ErrorHandling["Error Handling"]
Rendering --> Display["Display Output"]
ErrorHandling --> ErrorMessage["Show Error Message"]
Display --> RawToggle["Raw Toggle"]
RawToggle --> RawModal["Raw Data Modal"]
Loading

Diagram sources

  • codec.js

Mode Switching

The codec supports seamless switching between decode and encode modes:

Mode Configuration

const MODE_CONFIG = {
    decode: {
        panelId: 'codec-decode-panel',
        inputId: 'decoder-input',
        outputId: 'decoder-output',
        summaryId: 'decoded-content',
        toggleRawId: 'decoder-toggle-raw',
        statusKey: 'decoder',
        progressId: 'decoder-progress'
    },
    encode: {
        panelId: 'codec-encode-panel',
        inputId: 'encoder-input',
        outputId: 'encoder-output',
        summaryId: 'encoded-content',
        toggleRawId: 'encoder-toggle-raw',
        statusKey: 'encoder',
        progressId: 'encoder-progress',
        formatSelectId: 'encoder-format'
    }
};

Animation Support

Smooth transitions between modes with visual feedback:

// Switch mode with animation
switchCodecMode('encode');

// Animation triggers visual transition
content.classList.add('codec-mode-animating');
content.addEventListener('animationend', () => {
    content.classList.remove('codec-mode-animating');
}, { once: true });

Section sources

  • codec.js

Result Rendering

Sophisticated rendering of decoded results with interactive features:

Structured Display

// Build sections for different data types
const sections = buildSections(type, data);
if (sections.length === 0) {
    const emptySection = document.createElement('div');
    emptySection.className = 'decoder-empty';
    emptySection.textContent = 'No structured data available.';
    sectionsWrapper.appendChild(emptySection);
}

Interactive Elements

  • Expandable sections
  • Copy-to-clipboard functionality
  • Raw data access
  • Error highlighting

Section sources

  • codec.js

Template Integration

The codec integrates seamlessly with the application template system:

HTML Structure

<div id="codec-tab" class="tab-content">
    <div class="codec-mode-tabs" role="tablist">
        <button id="codec-mode-decode" class="codec-mode-tab active" 
                onclick="switchCodecMode('decode')">
            Decode
        </button>
        <button id="codec-mode-encode" class="codec-mode-tab" 
                onclick="switchCodecMode('encode')">
            Encode
        </button>
    </div>
    
    <div id="codec-mode-content" class="codec-mode-content">
        <!-- Decode Panel -->
        <div id="codec-decode-panel" class="codec-panel is-active">
            <!-- Input, buttons, output -->
        </div>
        
        <!-- Encode Panel -->
        <div id="codec-encode-panel" class="codec-panel">
            <!-- Format selector, input, buttons, output -->
        </div>
    </div>
</div>

Section sources

  • tab.html

Component Integration Patterns

The UI components work together through well-defined integration patterns that ensure consistency and reliability across the application.

State Management

Components share state through a centralized state management system:

// Shared state structure
const state = {
    storedCredentials: [],
    generatedExcludeCredentials: [],
    generatedAllowCredentials: [],
    currentSubTab: 'registration',
    // ... other shared state
};

Event Communication

Components communicate through standardized event patterns:

Custom Events

// Tab change notification
document.dispatchEvent(new CustomEvent('tab:changed', {
    detail: { tab: 'advanced' }
}));

// Subtab change notification
document.dispatchEvent(new CustomEvent('advanced:subtab-changed'));

Callback Integration

// Register callbacks for state changes
registerHintsChangeCallback(() => updateJsonEditor());

Backend Integration

All components integrate with backend services for data persistence and processing:

Credential Management

// Fetch credential artifacts from server
const artifact = await fetchCredentialArtifact(storageId);

// Delete credentials
await deleteCredentialArtifact(storageId);

Metadata Operations

// Load MDS metadata
const metadata = await fetchMdsMetadata();

// Upload custom metadata
const uploadResult = await uploadCustomMetadata(file);

Section sources

  • credential-display.js
  • mds.js

Performance Considerations

The UI components are designed with performance optimization in mind, particularly for handling large datasets and complex operations.

Memory Management

Lazy Loading Strategies

  • MDS browser uses progressive loading for large metadata sets
  • Credential display implements virtual scrolling for large credential lists
  • JSON editor uses streaming parsing for large payloads

Garbage Collection Optimization

// Efficient cleanup of unused data
function cleanupUnusedData() {
    // Remove references to large objects
    // Clear caches periodically
    // Release DOM references
}

Rendering Performance

Debounced Updates

// Debounce expensive operations
const debouncedUpdate = debounce(() => {
    updateCredentialsDisplay();
}, 300);

Virtual Scrolling

For large lists, components implement virtual scrolling to maintain performance:

// Only render visible items
const visibleItems = items.slice(startIndex, endIndex);

Batch Processing

Large operations are processed in batches to maintain UI responsiveness:

// Process in chunks to prevent blocking
async function processInBatches(items, batchSize = 100) {
    for (let i = 0; i < items.length; i += batchSize) {
        const batch = items.slice(i, i + batchSize);
        await processBatch(batch);
        await yieldToBrowser(); // Allow UI updates
    }
}

Network Optimization

Request Caching

// Cache metadata responses
const metadataCache = new Map();

async function getCachedMetadata(url) {
    if (metadataCache.has(url)) {
        return metadataCache.get(url);
    }
    
    const response = await fetch(url);
    const data = await response.json();
    metadataCache.set(url, data);
    return data;
}

Concurrent Processing

// Process multiple requests concurrently
const results = await Promise.allSettled([
    fetchCredentialData(),
    fetchMetadata(),
    fetchCertificates()
]);

Accessibility Features

All UI components implement comprehensive accessibility features to ensure usability for all users.

Keyboard Navigation

Universal Keyboard Support

  • Full keyboard navigation for all interactive elements
  • Tab order follows logical flow
  • Escape key support for modal dialogs
  • Enter/Space key activation for buttons

Screen Reader Support

// ARIA attributes for screen readers
<button 
    class="btn btn-small btn-secondary credential-mds-button"
    data-aaguid="${escapeHtml(aaguidGuid.toLowerCase())}"
    title="Open authenticator metadata"
    aria-label="Open authenticator metadata for ${cred.userName}"
    role="button"
    tabindex="0">
    FIDO MDS
</button>

Visual Accessibility

High Contrast Support

/* High contrast mode support */
@media (prefers-contrast: high) {
    .credential-item {
        border: 2px solid currentColor;
    }
    
    .credential-feature-tag {
        background-color: var(--high-contrast-bg);
        color: var(--high-contrast-text);
    }
}

Focus Indicators

/* Clear focus indicators */
.credential-item:focus {
    outline: 2px solid var(--focus-color);
    outline-offset: 2px;
}

Semantic Markup

Proper HTML Structure

<!-- Proper heading hierarchy -->
<h3 style="color: #0072CE; margin-bottom: 0.75rem;">Attestation Information</h3>

<!-- Logical grouping -->
<section style="margin-bottom: 1.5rem;">
    <h3 style="color: #0072CE; margin-bottom: 0.75rem;">Authenticator Response</h3>
    <ol style="padding-left: 1.25rem; margin: 0;">
        <li style="margin-bottom: 1rem;">
            <div style="font-weight: 600; margin-bottom: 0.5rem;">Response for navigator.credentials.create()</div>
            <!-- Content -->
        </li>
    </ol>
</section>

Troubleshooting Guide

Common issues and their solutions for the UI components.

Credential Display Issues

Problem: Credentials Not Loading

Symptoms: Empty credential list despite having saved credentials Solution:

// Check if credentials are properly synced
await ensureAdvancedCredentialArtifactsSynced();

// Verify state is populated
console.log('Stored credentials:', state.storedCredentials);

Problem: Attestation Data Missing

Symptoms: No attestation information displayed for credentials Solution:

// Force hydration of credential data
await hydrateCredentialFromServer(credential);

// Check for network errors
if (cred.__artifactHydrated === 'error') {
    console.error('Failed to load credential artifact');
}

JSON Editor Problems

Problem: Validation Errors

Symptoms: Editor shows validation errors for valid data Solution:

// Check validation rules
const validationRules = {
    KNOWN_REGISTRATION_PUBLIC_KEY_KEYS: new Set([
        'rp', 'user', 'challenge', 'pubKeyCredParams', 
        'timeout', 'authenticatorSelection', 'attestation', 
        'extensions', 'excludeCredentials', 'hints'
    ])
};

// Verify data structure matches expected format

Problem: Auto-indentation Not Working

Symptoms: Manual indentation required for JSON formatting Solution:

// Check keyboard event handlers
document.getElementById('json-editor').addEventListener('keydown', handleJsonEditorKeydown);

MDS Browser Issues

Problem: Metadata Not Loading

Symptoms: MDS tab shows loading indefinitely Solution:

// Check MDS initialization
const mdsState = getMdsLoadState();
if (!mdsState.hasLoaded) {
    await waitForMdsLoad();
}

// Verify network connectivity
const metadata = await fetchMdsMetadata();

Problem: Filter Dropdown Not Working

Symptoms: Dropdown doesn't show options or responds to clicks Solution:

// Check dropdown initialization
const dropdown = createFilterDropdown(inputElement, onSelect);
dropdown.setOptions(['Option 1', 'Option 2']);

// Verify event listeners
inputElement.addEventListener('focus', () => dropdown.open());

Codec Component Problems

Problem: Encoding/Decoding Failures

Symptoms: Payload processing fails with unclear errors Solution:

// Check input format
const input = document.getElementById('decoder-input').value;
if (!input.trim()) {
    showStatus('decoder', 'Input is empty', 'error');
    return;
}

// Verify backend service availability
try {
    const response = await fetch('/api/codec', { method: 'POST' });
    if (!response.ok) {
        throw new Error(`Server responded with status ${response.status}`);
    }
} catch (error) {
    showStatus('decoder', 'Backend service unavailable', 'error');
}

Performance Issues

Problem: Slow UI Responsiveness

Symptoms: UI becomes unresponsive during operations Solution:

// Implement async processing
async function processLargeDataset(dataset) {
    for (let i = 0; i < dataset.length; i += 100) {
        const chunk = dataset.slice(i, i + 100);
        await processChunk(chunk);
        await new Promise(resolve => setTimeout(resolve, 0)); // Yield to browser
    }
}

// Use requestIdleCallback for background tasks
if (typeof requestIdleCallback === 'function') {
    requestIdleCallback(() => {
        // Perform background processing
    });
}

Debugging Tools

Enable Debug Logging

// Add debug logging to components
function logDebug(message, data) {
    if (process.env.NODE_ENV === 'development') {
        console.log(`[DEBUG] ${message}`, data);
    }
}

// Usage in components
logDebug('Credential display updated', { count: state.storedCredentials.length });

State Inspection

// Inspect component state
function inspectComponentState(componentName) {
    const state = window[componentName]?.getState?.();
    console.log(`${componentName} state:`, state);
}

Section sources

  • credential-display.js
  • json-editor.js
  • mds.js
  • codec.js

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