9.3 KiB
WebCryptoAPI Authentication Implementation
This document describes the complete WebCryptoAPI authentication system implemented in this project.
Overview
The WebCryptoAPI authentication system provides cryptographic authentication using ECDSA P-256 key pairs, challenge-response authentication, and secure key storage. This is the primary authentication mechanism for the application.
Architecture
Core Components
-
Crypto Module (
src/lib/auth/crypto.ts)- WebCryptoAPI wrapper functions
- Key pair generation (ECDSA P-256)
- Public key export/import
- Data signing and verification
- User credential storage
-
CryptoAuthService (
src/lib/auth/cryptoAuthService.ts)- High-level authentication service
- Challenge-response authentication
- User registration and login
- Credential verification
-
AuthService (
src/lib/auth/authService.ts)- Simplified authentication service
- Session management
- Integration with CryptoAuthService
-
UI Components
CryptID.tsx- Cryptographic authentication UICryptoDebug.tsx- Debug component for verificationCryptoTest.tsx- Test component for verification
Features
✅ Implemented
- ECDSA P-256 Key Pairs: Secure cryptographic key generation
- Challenge-Response Authentication: Prevents replay attacks
- Public Key Infrastructure: Store and verify public keys
- Browser Support Detection: Checks for WebCryptoAPI availability
- Secure Context Validation: Ensures HTTPS requirement
- Modern UI: Responsive design with dark mode support
- Comprehensive Testing: Test component for verification
🔧 Technical Details
Key Generation
const keyPair = await crypto.generateKeyPair();
// Returns CryptoKeyPair with public and private keys
Public Key Export/Import
const publicKeyBase64 = await crypto.exportPublicKey(keyPair.publicKey);
const importedKey = await crypto.importPublicKey(publicKeyBase64);
Data Signing and Verification
const signature = await crypto.signData(privateKey, data);
const isValid = await crypto.verifySignature(publicKey, signature, data);
Challenge-Response Authentication
// Generate challenge
const challenge = `${username}:${timestamp}:${random}`;
// Sign challenge during registration
const signature = await crypto.signData(privateKey, challenge);
// Verify during login
const isValid = await crypto.verifySignature(publicKey, signature, challenge);
Browser Requirements
Minimum Requirements
- WebCryptoAPI Support:
window.crypto.subtle - Secure Context: HTTPS or localhost
- Modern Browser: Chrome 37+, Firefox 34+, Safari 11+, Edge 12+
Feature Detection
const hasWebCrypto = typeof window.crypto !== 'undefined' &&
typeof window.crypto.subtle !== 'undefined';
const isSecure = window.isSecureContext;
Security Considerations
✅ Implemented Security Measures
- Secure Context Requirement: Only works over HTTPS
- ECDSA P-256: Industry-standard elliptic curve
- Challenge-Response: Prevents replay attacks
- Key Storage: Public keys stored securely in localStorage
- Input Validation: Username format validation
- Error Handling: Comprehensive error management
⚠️ Security Notes
-
Private Key Storage: Currently uses localStorage for demo purposes
- In production, consider using Web Crypto API's non-extractable keys
- Consider hardware security modules (HSM)
- Implement proper key derivation
-
Session Management:
- Uses localStorage for session persistence
- Consider implementing JWT tokens for server-side verification
- Add session expiration and refresh logic
-
Network Security:
- All crypto operations happen client-side
- No private keys transmitted over network
- Consider adding server-side signature verification
Usage
Basic Authentication Flow
import { CryptoAuthService } from './lib/auth/cryptoAuthService';
// Register a new user
const registerResult = await CryptoAuthService.register('username');
if (registerResult.success) {
console.log('User registered successfully');
}
// Login with existing user
const loginResult = await CryptoAuthService.login('username');
if (loginResult.success) {
console.log('User authenticated successfully');
}
Integration with React Context
import { useAuth } from './context/AuthContext';
const { login, register } = useAuth();
// AuthService automatically uses crypto auth
const success = await login('username');
Using the CryptID Component
import CryptID from './components/auth/CryptID';
// Render the authentication component
<CryptID
onSuccess={() => console.log('Login successful')}
onCancel={() => console.log('Login cancelled')}
/>
Testing the Implementation
import CryptoTest from './components/auth/CryptoTest';
// Render the test component to verify functionality
<CryptoTest />
File Structure
src/
├── lib/
│ ├── auth/
│ │ ├── crypto.ts # WebCryptoAPI wrapper
│ │ ├── cryptoAuthService.ts # High-level auth service
│ │ ├── authService.ts # Simplified auth service
│ │ ├── sessionPersistence.ts # Session storage utilities
│ │ └── types.ts # TypeScript types
│ └── utils/
│ └── browser.ts # Browser support detection
├── components/
│ └── auth/
│ ├── CryptID.tsx # Main crypto auth UI
│ ├── CryptoDebug.tsx # Debug component
│ └── CryptoTest.tsx # Test component
├── context/
│ └── AuthContext.tsx # React context for auth state
└── css/
└── crypto-auth.css # Styles for crypto components
Dependencies
Required Packages
one-webcrypto: WebCryptoAPI polyfill (^1.0.3)
Browser APIs Used
window.crypto.subtle: WebCryptoAPIwindow.localStorage: Key and session storagewindow.isSecureContext: Security context check
Storage
localStorage Keys Used
registeredUsers: Array of registered usernames${username}_publicKey: User's public key (Base64)${username}_authData: Authentication data (challenge, signature, timestamp)session: Current user session data
Testing
Manual Testing
- Navigate to the application
- Use the
CryptoTestcomponent to run automated tests - Verify all test cases pass
- Test on different browsers and devices
Test Cases
- Browser support detection
- Secure context validation
- Key pair generation
- Public key export/import
- Data signing and verification
- User registration
- User login
- Credential verification
- Session persistence
Troubleshooting
Common Issues
-
"Browser not supported"
- Ensure you're using a modern browser
- Check if WebCryptoAPI is available
- Verify HTTPS or localhost
-
"Secure context required"
- Access the application over HTTPS
- For development, use localhost
-
"Key generation failed"
- Check browser console for errors
- Verify WebCryptoAPI permissions
- Try refreshing the page
-
"Authentication failed"
- Verify user exists in localStorage
- Check stored credentials
- Clear browser data and retry
Debug Mode
Enable debug logging by opening the browser console:
localStorage.setItem('debug_crypto', 'true');
Future Enhancements
Planned Improvements
- Enhanced Key Storage: Use Web Crypto API's non-extractable keys
- Server-Side Verification: Add server-side signature verification
- Multi-Factor Authentication: Add additional authentication factors
- Key Rotation: Implement automatic key rotation
- Hardware Security: Support for hardware security modules
Advanced Features
- Zero-Knowledge Proofs: Implement ZKP for enhanced privacy
- Threshold Cryptography: Distributed key management
- Post-Quantum Cryptography: Prepare for quantum threats
- Biometric Integration: Add biometric authentication
Integration with Automerge Sync
The authentication system works seamlessly with the Automerge-based real-time collaboration:
- User Identification: Each user is identified by their username in Automerge
- Session Management: Sessions persist across page reloads via localStorage
- Collaboration: Authenticated users can join shared canvas rooms
- Privacy: Only authenticated users can access canvas data
Contributing
When contributing to the WebCryptoAPI authentication system:
- Security First: All changes must maintain security standards
- Test Thoroughly: Run the test suite before submitting
- Document Changes: Update this documentation
- Browser Compatibility: Test on multiple browsers
- Performance: Ensure crypto operations don't block UI