usePasskey
Manage passkey registration, authentication, and credential operations.
Framework Support: Available in all HelioRim SDK frameworks
Import
import { usePasskey } from '@heliorim/sdk-react';
// or
import { usePasskey } from '@heliorim/sdk-vue';Type Signature
interface PasskeyState {
isRegistering: boolean;
isAuthenticating: boolean;
credentials: Credential[];
currentCredential: Credential | null;
error: Error | null;
isSupported: boolean;
isConditionalUIAvailable: boolean;
}
interface PasskeyActions {
register: (options: RegisterOptions) => Promise<Credential>;
authenticate: (options?: AuthenticateOptions) => Promise<void>;
listCredentials: () => Promise<Credential[]>;
deleteCredential: (credentialId: string) => Promise<void>;
renameCredential: (credentialId: string, name: string) => Promise<void>;
clearError: () => void;
}
interface RegisterOptions {
email: string;
displayName: string;
userVerification?: 'required' | 'preferred' | 'discouraged';
authenticatorAttachment?: 'platform' | 'cross-platform';
residentKey?: 'required' | 'preferred' | 'discouraged';
}
interface AuthenticateOptions {
email?: string;
userVerification?: 'required' | 'preferred' | 'discouraged';
conditionalUI?: boolean;
}
interface Credential {
id: string;
publicKey: string;
name: string;
createdAt: number;
lastUsedAt?: number;
authenticatorAttachment?: 'platform' | 'cross-platform';
backupEligible?: boolean;
backupState?: boolean;
}
type UsePasskeyReturn = PasskeyState & PasskeyActions;Basic Usage
function PasskeyManager() {
const {
isRegistering,
isAuthenticating,
credentials,
isSupported,
register,
authenticate,
listCredentials,
deleteCredential
} = usePasskey();
const handleRegister = async () => {
try {
const credential = await register({
email: 'user@example.com',
displayName: 'John Doe',
userVerification: 'required',
authenticatorAttachment: 'platform'
});
console.log('Registered:', credential);
} catch (err) {
console.error('Registration failed:', err);
}
};
const handleLogin = async () => {
try {
await authenticate({
userVerification: 'required'
});
// Authentication successful
} catch (err) {
console.error('Authentication failed:', err);
}
};
if (!isSupported) {
return <div>Passkeys not supported on this device</div>;
}
return (
<div>
<button
onClick={handleRegister}
disabled={isRegistering}
>
{isRegistering ? 'Registering...' : 'Register Passkey'}
</button>
<button
onClick={handleLogin}
disabled={isAuthenticating}
>
{isAuthenticating ? 'Authenticating...' : 'Sign In'}
</button>
<div>
<h3>Your Passkeys</h3>
{credentials.map(cred => (
<div key={cred.id}>
<span>{cred.name}</span>
<button onClick={() => deleteCredential(cred.id)}>
Delete
</button>
</div>
))}
</div>
</div>
);
}Return Values
isRegistering
boolean - Registration ceremony in progress
isAuthenticating
boolean - Authentication ceremony in progress
credentials
Credential[] - List of user's registered passkeys
isSupported
boolean - Whether WebAuthn is supported in current browser
isConditionalUIAvailable
boolean - Whether conditional UI (autofill) is available
register(options)
Promise<Credential> - Register a new passkey for the user
authenticate(options?)
Promise<void> - Authenticate using a passkey
listCredentials()
Promise<Credential[]> - Fetch all user's passkeys
deleteCredential(id)
Promise<void> - Delete a specific passkey
renameCredential(id, name)
Promise<void> - Rename a passkey for easier identification
Advanced Features
Conditional UI (Autofill)
function LoginWithAutofill() {
const { authenticate, isConditionalUIAvailable } = usePasskey();
useEffect(() => {
if (isConditionalUIAvailable) {
// Start conditional UI - passkeys appear in autofill
authenticate({ conditionalUI: true }).catch(() => {
// User didn't select a passkey from autofill
});
}
}, [isConditionalUIAvailable]);
return (
<form>
<input
type="email"
autoComplete="username webauthn"
placeholder="Email"
/>
<button type="submit">Continue</button>
</form>
);
}Platform vs Cross-Platform
function RegisterOptions() {
const { register } = usePasskey();
const registerPlatform = () => {
// Prefers built-in authenticator (Touch ID, Windows Hello)
register({
email: 'user@example.com',
displayName: 'User',
authenticatorAttachment: 'platform',
residentKey: 'required' // Discoverable credential
});
};
const registerCrossPlatform = () => {
// Allows USB security keys, phones
register({
email: 'user@example.com',
displayName: 'User',
authenticatorAttachment: 'cross-platform'
});
};
return (
<>
<button onClick={registerPlatform}>
Use This Device
</button>
<button onClick={registerCrossPlatform}>
Use Security Key
</button>
</>
);
}Backup State Detection
function CredentialList() {
const { credentials } = usePasskey();
return (
<ul>
{credentials.map(cred => (
<li key={cred.id}>
<span>{cred.name}</span>
{cred.backupEligible && (
<span className="badge">
{cred.backupState ? '☁️ Synced' : '📱 Device-only'}
</span>
)}
</li>
))}
</ul>
);
}User Verification Levels
const { authenticate } = usePasskey();
// High security - always require biometric/PIN
await authenticate({
userVerification: 'required'
});
// Balanced - use if available
await authenticate({
userVerification: 'preferred'
});
// Low friction - skip if possible
await authenticate({
userVerification: 'discouraged'
});Error Handling
const { register, error } = usePasskey();
try {
await register(options);
} catch (err) {
switch(err.name) {
case 'NotAllowedError':
// User cancelled or timeout
break;
case 'InvalidStateError':
// Credential already exists
break;
case 'NotSupportedError':
// Algorithm or option not supported
break;
case 'SecurityError':
// Origin not allowed
break;
case 'AbortError':
// Operation was aborted
break;
}
}Browser Compatibility
WebAuthn Support Required:
- Chrome/Edge 67+ (Desktop & Mobile)
- Safari 14+ (macOS 11+, iOS 14+)
- Firefox 60+ (Limited mobile support)
- No support: Internet Explorer, older browsers
Best Practices
✓ DO
- Check
isSupportedbefore showing passkey options - Provide fallback authentication methods
- Allow users to name their credentials
- Show backup state to users
- Handle all error cases gracefully
✗ DON'T
- Force passkey-only authentication
- Store private keys (they never leave the authenticator)
- Assume all devices support platform authenticators
- Skip user verification for sensitive operations