A modern WebAuthn/Passkeys library for browser authentication that generates deterministic private keys from authenticator signatures.
- β WebAuthn/Passkeys Authentication: Full WebAuthn standard support
- π Deterministic private keys: Generate reproducible private keys from passkey signatures
- π Browser-first: Optimized for client-side usage
- π Cryptographically secure: Uses HKDF with SHA-256 for key derivation
- π± Platform authenticators: Support for Face ID, Touch ID, Windows Hello
- π― Simple API: Easy-to-use interface for authentication workflows
bun add passkey39import { Passkey39, isWebAuthnSupported } from 'passkey39'
// Check WebAuthn support
if (!isWebAuthnSupported()) {
throw new Error('WebAuthn is not supported in this browser')
}
// Initialize with your relying party name
const passkeys = new Passkey39({
rpName: 'example.com'
})
// Create a new passkey for a user
await passkeys.createPasskeys('user@example.com')
// Authenticate and get deterministic private key
const privateKey = await passkeys.authenticate('user@example.com')
console.log('Private key (hex):', privateKey.hex)
console.log('Private key (bytes):', privateKey.bytes)
console.log('BIP39 mnemonic:', privateKey.mnemonic)new Passkey39({
rpName: string, // Required: Your domain/app name
challenge?: string // Optional: Custom challenge (has secure default)
})Creates a new passkey for the specified user. This should be called once per user to register their authenticator.
await passkeys.createPasskeys('user@example.com')Authenticates the user and returns their deterministic private key.
const privateKey = await passkeys.authenticate('user@example.com')hex: string- Private key as hexadecimal stringbytes: Uint8Array- Private key as byte arraymnemonic: string- Private key as BIP39 mnemonic phrase (24 words)
Checks if WebAuthn is supported in the current browser environment.
if (isWebAuthnSupported()) {
// WebAuthn is available
}- Deterministic keys: The same passkey will always generate the same private key
- Domain-bound: Keys are tied to your domain (
rpNameandwindow.location.origin) - User-specific: Each username gets a unique private key
- Cryptographically secure: Uses HKDF-SHA256 for key derivation
- Platform authenticators: Requires user verification (biometrics/PIN)
Requires a browser with WebAuthn support:
- β Chrome 67+
- β Firefox 60+
- β Safari 14+
- β Edge 18+
- Bun runtime
# Install dependencies
bun install
# Run tests
bun test
# Build the library
bun run build
# Clean build artifacts
bun run cleanimport { Passkey39, isWebAuthnSupported } from 'passkey39'
async function setupAuthentication() {
// Check browser support
if (!isWebAuthnSupported()) {
alert('Your browser does not support WebAuthn')
return
}
const passkeys = new Passkey39({
rpName: 'myapp.com'
})
const username = 'alice@example.com'
try {
// First time: create passkey
console.log('Creating passkey...')
await passkeys.createPasskeys(username)
console.log('β
Passkey created successfully')
// Subsequent times: authenticate
console.log('Authenticating...')
const privateKey = await passkeys.authenticate(username)
console.log('π Private key:', privateKey.hex)
console.log('π― Mnemonic:', privateKey.mnemonic)
} catch (error) {
console.error('β Authentication failed:', error)
}
}
setupAuthentication()MIT