Table of Contents
- UI Components
- Table of Contents
- Introduction
- Credential Display Component
- JSON Editor Implementation
- MDS Browser Functionality
- Settings Navigation Component
- Decoder/Encoder Interface
- Codec Architecture
- Supported Formats
- Processing Pipeline
- Mode Switching
- Result Rendering
- Template Integration
- Component Integration Patterns
- Performance Considerations
- Accessibility Features
- Troubleshooting Guide
UI Components
Table of Contents
- Introduction
- Credential Display Component
- JSON Editor Implementation
- MDS Browser Functionality
- Settings Navigation Component
- Decoder/Encoder Interface
- Component Integration Patterns
- Performance Considerations
- Accessibility Features
- 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"
Diagram sources
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
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
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"
Diagram sources
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
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
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"
Diagram sources
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
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
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
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"
Diagram sources
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
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
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"
Diagram sources
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"]
Diagram sources
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
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
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
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
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