PricingDemo
Log InGet API Key
Tutorial

React Biometric Login with H33

|Eric Beans, CEO|14 min read

Adding biometric authentication to a React application traditionally requires either delegating to a third-party service that handles (and sees) your users' biometric data, or building a custom biometric pipeline that involves complex computer vision, template management, and matching logic. H33's React SDK provides a third option: biometric authentication where the biometric data is encrypted on the user's device and the server never sees it in plaintext.

This tutorial walks through building a complete biometric login flow in React using the H33 SDK. By the end, you will have a working implementation where users authenticate with their face, all biometric processing happens in the encrypted domain, and your server never handles plaintext biometric data.

Prerequisites

You need a React application (Create React App, Next.js, Vite, or any React setup), an H33 API key (available at h33.ai/pricing, free tier available for development), and Node.js 18 or later. No cryptography expertise is required. The SDK handles all FHE encryption, key management, and API communication internally.

Installation

Install the H33 React biometric SDK from npm. The package includes the React components, the FHE engine (compiled to WebAssembly for browser execution), and the API client. The WebAssembly module handles the computationally intensive BFV encryption operations at near-native speed in the browser.

The SDK exports three primary components: BiometricProvider (context provider that initializes the FHE engine), BiometricCapture (camera component for face capture), and useH33Auth (hook for authentication state management). These compose together to create a complete biometric login flow with minimal boilerplate code.

Setting Up the Provider

Wrap your application (or the authenticated section) with BiometricProvider, passing your H33 API key. The provider initializes the FHE engine on mount, generating the key pair (public key for encryption, private key for decryption) in the browser. The private key never leaves the browser. The public key is sent to the H33 backend so it can return encrypted results that only the user's browser can decrypt.

Initialization takes approximately 200 to 500 milliseconds depending on the device. The provider exposes a ready state through context so you can show a loading indicator while the FHE engine initializes. Once ready, all subsequent operations (encryption, decryption) are fast because the key material is cached in memory.

The Enrollment Flow

Enrollment captures the user's face, extracts a feature vector using a client-side neural network (included in the SDK), encrypts the vector using BFV, and sends the encrypted template to the H33 API for storage. The enrollment component uses the BiometricCapture component with mode set to enroll.

The capture component activates the device camera through the WebRTC API, guides the user to position their face correctly (using on-screen indicators for distance, angle, and lighting), captures multiple frames for quality, selects the best frame, and extracts the feature vector. All of this happens client-side. The feature vector is then encrypted using the BFV public key and sent to the API as an encrypted enrollment request.

The server stores the encrypted template. It cannot decrypt it because it does not have the private key. The enrollment is confirmed with an H33-74 attestation that proves the template was stored correctly.

The Authentication Flow

Authentication captures a fresh face image, extracts and encrypts the feature vector, sends it to the API, receives the encrypted match score, and decrypts it locally. The useH33Auth hook provides a simple authenticate method that handles this entire flow.

When the user clicks the login button, the authenticate method activates the camera, captures and encrypts the biometric sample, sends the encrypted probe to the H33 API, receives the encrypted match score, decrypts the score locally, compares it against the configurable threshold, and returns either a success result with an authentication token or a failure result with the reason (no match, poor quality, timeout).

The entire flow takes approximately one to two seconds from camera activation to authentication result, including network round trips. The FHE computation on the server adds approximately 30 to 50 milliseconds, which is a small fraction of the total time dominated by camera activation and image capture.

Handling Authentication State

The useH33Auth hook manages authentication state including loading indicators, error handling, retry logic, and session management. On successful authentication, the hook returns an H33 authentication token that can be used for subsequent API calls. The token includes the H33-74 attestation proving that a valid biometric match occurred in the encrypted domain.

Failed authentications return structured error information: whether the failure was due to no match (the biometric did not match the enrolled template), poor quality (the capture was too blurry, too dark, or too angled), timeout (the user did not present their face in time), or network error (the API was unreachable). Each error type can be handled differently in the UI.

Security Properties

The security properties of this implementation are worth enumerating explicitly. The plaintext biometric data never leaves the user's device. The FHE private key never leaves the user's device. The server never sees plaintext biometric data at any point, including during matching. The match computation happens entirely in the encrypted domain using BFV. The authentication result is attested with H33-74 three-family post-quantum signatures. The entire pipeline is quantum-resistant through lattice-based FHE and three-family PQ signatures.

These properties hold regardless of server compromise. If your server is breached, the attacker obtains encrypted ciphertexts that are useless without the private keys stored on users' devices. This is fundamentally different from traditional biometric services where a server breach exposes plaintext biometric data permanently.

Production Considerations

For production deployment, consider implementing progressive enrollment (capture multiple angles over several sessions for better template quality), fallback authentication (password or OTP for devices without cameras), accessibility (screen reader support, alternative input methods), and analytics (track authentication success rates, capture quality distributions, and latency percentiles to identify and resolve issues).

The H33 React SDK handles the cryptographic complexity. Your job as a developer is to create a good user experience around the biometric capture and to handle the authentication results appropriately in your application's auth flow. The encryption, matching, and attestation happen behind a clean API that abstracts away the FHE, STARK, and PQ signature machinery.

Advanced Integration Patterns

Beyond the basic login flow, several advanced integration patterns enable richer biometric experiences in React applications.

Progressive enrollment: Instead of capturing all enrollment data in a single session, progressive enrollment captures additional biometric samples over the user's first several authentications. Each successful authentication provides a new sample that improves the enrolled template through H33's incremental auth delta update mechanism. The user enrolls with a single face capture and the template quality improves automatically over the next week of use.

Multi-modal authentication: For high-security applications, the SDK supports combining face recognition with WebAuthn-based fingerprint authentication (on supported devices). The BiometricCapture component accepts an array of modalities, and the useH33Auth hook manages the combined authentication flow. Both biometric modalities are encrypted independently using BFV, and the FHE matching pipeline produces separate match scores that are fused homomorphically on the server.

Continuous authentication: For applications that require ongoing user verification (financial trading platforms, healthcare record access), the SDK provides a continuous mode where the camera remains active and the biometric is re-verified at configurable intervals (every 30 seconds, every minute, etc.). If the continuous check fails (the user has left the device or a different person is present), the session is suspended until re-authentication succeeds.

Fallback chains: The useH33Auth hook supports configurable fallback chains. If face recognition fails (poor lighting, camera blocked), the hook can automatically fall back to fingerprint authentication via WebAuthn, then to a traditional TOTP code, then to email-based magic link. Each fallback level is logged and attested with H33-74, creating a verifiable record of the authentication method used.

Performance Optimization

Several optimization techniques improve the perceived performance of biometric login in React applications.

Eager initialization: Initialize the BiometricProvider as early as possible in the application lifecycle, even before the user navigates to the login page. The FHE engine initialization (200 to 500 milliseconds) can happen during the application's splash screen or landing page, so the login page is immediately ready when the user arrives.

Camera pre-warming: On devices where camera activation is slow (some Android devices take 500+ milliseconds), pre-warm the camera when the user approaches the login page (detected through scroll position or navigation intent). The BiometricCapture component accepts a preWarm prop that activates the camera without displaying the preview, reducing the perceived capture latency.

Optimistic UI: After the biometric capture completes and the encrypted data is sent to the API, show a progress indicator with "Verifying..." rather than blocking the UI. The verification typically completes in under 100 milliseconds (including network latency), so the optimistic UI creates a seamless experience where the transition from capture to authenticated state feels instantaneous.

Error Handling Best Practices

Robust error handling is essential for biometric authentication because failures are more common and more varied than password-based authentication. The SDK provides structured error types that map to user-actionable guidance.

CaptureQualityError indicates the biometric capture did not meet quality thresholds. The recommended UX is to show specific guidance: "Move closer" (face too small), "Improve lighting" (too dark), "Hold steady" (motion blur), or "Remove obstructions" (face partially covered). The error object includes the specific quality metric that failed.

MatchError indicates the biometric did not match the enrolled template. The recommended UX is to offer a retry with guidance to capture a better sample, followed by fallback to an alternative authentication method after two to three failures. Do not tell the user that the biometric "did not match" because this can create anxiety; instead say "Let's try again" or offer the alternative method.

NetworkError indicates the API was unreachable. The recommended UX is to retry automatically (the SDK includes exponential backoff) and show a connection status indicator. If the user is in an area with poor connectivity, offer offline-capable fallback authentication.

The H33 React SDK handles the cryptographic complexity of encrypted biometric authentication. What remains for the application developer is creating a smooth, accessible, and error-tolerant user experience around the biometric capture and verification flow. The encryption, matching, attestation, and post-quantum security happen automatically behind the clean API surface that the SDK provides.

Build Encrypted Biometric Auth

Get your API key and start building encrypted biometric login in React today.

Get API Key Read the Docs
Verify It Yourself