GenosDB’s Security Manager integrates WebAuthn (Web Authentication API) to provide passwordless, phishing-resistant authentication using biometrics, hardware security keys, or platform authenticators.
Overview
WebAuthn enables:
Passwordless Login No passwords to remember, type, or steal
Phishing-Resistant Cryptographic challenges prevent phishing attacks
Hardware-Backed Private keys stored in secure hardware (TPM, Secure Enclave)
Biometric Unlock Face ID, Touch ID, Windows Hello, fingerprint sensors
How It Works
GenosDB uses WebAuthn to encrypt/decrypt the user’s Ethereum private key:
Registration : User creates identity with mnemonic phrase
Protection : Private key is encrypted using WebAuthn-derived secret
Storage : Encrypted key stored in browser’s secure storage
Login : WebAuthn biometric/hardware challenge decrypts the key
Session : Decrypted key is used for signing operations
The private key never leaves the device and is only decrypted after successful WebAuthn verification.
Registration Flow
Step 1: Create New Identity
import { gdb } from 'genosdb' ;
const db = await gdb ( 'mydb' , {
rtc: true ,
sm: { superAdmins: [ '0x...' ] }
});
const sm = db . sm ;
// Create new Ethereum identity
const result = await sm . startNewUserRegistration ();
console . log ( 'Mnemonic (save this!):' , result . mnemonic );
console . log ( 'Ethereum Address:' , result . address );
// Display mnemonic to user for backup
Users must save their mnemonic phrase securely. It’s the only way to recover access if WebAuthn fails or on a new device.
Step 2: Protect with WebAuthn
try {
await sm . protectCurrentIdentityWithWebAuthn ();
console . log ( '✓ Identity protected with WebAuthn' );
// Private key is now encrypted and stored
} catch ( error ) {
console . error ( 'WebAuthn protection failed:' , error );
// Fallback: user must use mnemonic for future logins
}
What happens internally:
Browser prompts for biometric/hardware authenticator
WebAuthn creates a new credential tied to the origin
Credential’s public key is used to derive encryption key
User’s private key is encrypted with this key
Encrypted key is stored in browser storage
Login Flow
WebAuthn Login (Biometric)
const db = await gdb ( 'mydb' , {
rtc: true ,
sm: { superAdmins: [ '0x...' ] }
});
const sm = db . sm ;
try {
const address = await sm . loginCurrentUserWithWebAuthn ();
console . log ( '✓ Logged in as:' , address );
// User can now perform signed operations
} catch ( error ) {
console . error ( 'WebAuthn login failed:' , error );
// Show mnemonic input form
}
What happens internally:
Browser prompts for biometric/authenticator
WebAuthn verifies the user
Credential provides decryption key
Private key is decrypted into memory
User session is established
Mnemonic Login (Fallback)
If WebAuthn fails or user is on a new device:
const mnemonic = prompt ( 'Enter your 12-word mnemonic phrase' );
try {
const address = await sm . loginOrRecoverUserWithMnemonic ( mnemonic );
console . log ( '✓ Recovered identity:' , address );
// Optionally re-enable WebAuthn on this device
await sm . protectCurrentIdentityWithWebAuthn ();
} catch ( error ) {
console . error ( 'Invalid mnemonic' );
}
Session Management
Check Login Status
const address = sm . getActiveEthAddress ();
if ( address ) {
console . log ( 'Logged in as:' , address );
} else {
console . log ( 'Not logged in' );
// Show login form
}
Logout
await sm . clearSecurity ();
console . log ( 'Logged out' );
// Private key cleared from memory
// WebAuthn-protected key remains in storage for next login
UI Integration Example
Complete Authentication UI
import { gdb } from 'genosdb' ;
let db , sm ;
async function init () {
db = await gdb ( 'myapp' , {
rtc: true ,
sm: { superAdmins: [ '0xALICE...' ] }
});
sm = db . sm ;
updateUI ();
}
// Registration
async function handleRegister () {
try {
const { mnemonic , address } = await sm . startNewUserRegistration ();
// Show mnemonic to user
alert ( `SAVE THIS MNEMONIC: \n\n ${ mnemonic } \n\n Address: ${ address } ` );
// Enable WebAuthn
await sm . protectCurrentIdentityWithWebAuthn ();
updateUI ();
} catch ( error ) {
alert ( 'Registration failed: ' + error . message );
}
}
// WebAuthn Login
async function handleWebAuthnLogin () {
try {
const address = await sm . loginCurrentUserWithWebAuthn ();
console . log ( 'Logged in:' , address );
updateUI ();
} catch ( error ) {
alert ( 'WebAuthn login failed. Use mnemonic recovery.' );
}
}
// Mnemonic Login
async function handleMnemonicLogin () {
const mnemonic = prompt ( 'Enter your 12-word mnemonic:' );
if ( ! mnemonic ) return ;
try {
const address = await sm . loginOrRecoverUserWithMnemonic ( mnemonic );
console . log ( 'Recovered:' , address );
// Optionally re-enable WebAuthn
const enableWebAuthn = confirm ( 'Enable biometric login on this device?' );
if ( enableWebAuthn ) {
await sm . protectCurrentIdentityWithWebAuthn ();
}
updateUI ();
} catch ( error ) {
alert ( 'Invalid mnemonic' );
}
}
// Logout
async function handleLogout () {
await sm . clearSecurity ();
updateUI ();
}
// Update UI based on auth state
function updateUI () {
const address = sm . getActiveEthAddress ();
if ( address ) {
document . getElementById ( 'loginSection' ). style . display = 'none' ;
document . getElementById ( 'appSection' ). style . display = 'block' ;
document . getElementById ( 'userAddress' ). textContent = address ;
} else {
document . getElementById ( 'loginSection' ). style . display = 'block' ;
document . getElementById ( 'appSection' ). style . display = 'none' ;
}
}
init ();
HTML Structure
<!-- Login Section -->
< div id = "loginSection" >
< h2 > Login to GenosDB App </ h2 >
< button onclick = " handleWebAuthnLogin ()" > Login with Biometrics </ button >
< button onclick = " handleMnemonicLogin ()" > Recover with Mnemonic </ button >
< button onclick = " handleRegister ()" > Create New Account </ button >
</ div >
<!-- App Section -->
< div id = "appSection" style = "display: none" >
< p > Logged in as: < span id = "userAddress" ></ span ></ p >
< button onclick = " handleLogout ()" > Logout </ button >
<!-- Your app content here -->
</ div >
WebAuthn is supported by all modern browsers:
Browser Platform Authenticator Hardware Keys Chrome 67+ ✓ Windows Hello, Touch ID ✓ FIDO2 Firefox 60+ ✓ Windows Hello ✓ FIDO2 Safari 14+ ✓ Touch ID, Face ID ✓ FIDO2 Edge 18+ ✓ Windows Hello ✓ FIDO2
WebAuthn requires HTTPS or localhost for security. It will not work on http:// production sites.
Security Considerations
What WebAuthn Protects
Phishing Credential is origin-bound; can’t be used on fake sites
Keylogging No password to intercept
Database Breach Private key never sent to server
Man-in-the-Middle Cryptographic challenge-response prevents MITM
What WebAuthn Doesn’t Protect
Device Loss : If the user loses their device AND didn’t save their mnemonic, access is permanently lost. Always enforce mnemonic backup during registration.
Mitigation:
// Force mnemonic confirmation before enabling WebAuthn
const { mnemonic } = await sm . startNewUserRegistration ();
// Display mnemonic
alert ( `SAVE THIS: \n ${ mnemonic } ` );
// Verify user wrote it down
const confirmation = prompt ( 'Enter word #3 from your mnemonic:' );
const words = mnemonic . split ( ' ' );
if ( confirmation !== words [ 2 ]) {
alert ( 'Incorrect! Please write down your mnemonic.' );
return ;
}
// Now safe to enable WebAuthn
await sm . protectCurrentIdentityWithWebAuthn ();
Advanced: Multiple Devices
WebAuthn credentials are device-specific . For multi-device access:
Option 1: Mnemonic Recovery on New Device
// On new device
const mnemonic = /* user enters saved mnemonic */ ;
await sm . loginOrRecoverUserWithMnemonic ( mnemonic );
// Enable WebAuthn on this device too
await sm . protectCurrentIdentityWithWebAuthn ();
Some platforms (Apple, Google) are introducing synced passkeys:
iCloud Keychain syncs Touch ID/Face ID across Apple devices
Google Password Manager syncs across Chrome instances
These would allow seamless multi-device WebAuthn.
Troubleshooting
WebAuthn not available error
Cause : Browser doesn’t support WebAuthn or site is not HTTPSSolution :if ( ! window . PublicKeyCredential ) {
alert ( 'Your browser doesn \' t support WebAuthn. Please use Chrome 67+, Firefox 60+, or Safari 14+' );
// Fallback to mnemonic-only auth
}
NotAllowedError during registration
Cause : User cancelled the authenticator prompt or timeoutSolution : Let user retry or skip WebAuthntry {
await sm . protectCurrentIdentityWithWebAuthn ();
} catch ( error ) {
if ( error . name === 'NotAllowedError' ) {
console . log ( 'User cancelled authenticator' );
// Allow continuing without WebAuthn
}
}
Credential not found during login
Cause : User is on a different device or cleared browser dataSolution : Show mnemonic recovery optiontry {
await sm . loginCurrentUserWithWebAuthn ();
} catch ( error ) {
if ( error . name === 'NotFoundError' ) {
alert ( 'No saved credential. Please use mnemonic recovery.' );
showMnemonicInput ();
}
}
Works on localhost but not production
Cause : Production site is using HTTP instead of HTTPSSolution : Enable HTTPS on your production site. WebAuthn requires secure context.
Best Practices
Always enforce mnemonic backup before enabling WebAuthn
Provide mnemonic recovery as fallback login option
Test on target platforms (iOS Safari, Android Chrome, Windows, macOS)
Use clear UX explaining biometric/hardware key prompts
Handle errors gracefully with helpful messages
Consider privacy : Don’t force biometrics if user prefers mnemonic
Related Pages
RBAC Role-based access control system
Zero-Trust Model Security architecture principles