Skip to main content
This example shows how to integrate BioKey into a React application using the useBioKey hook from the biokey-react package.

Installation

Install both the React package and the core client library:
npm install biokey-react biokey-js

Complete Example

Here’s a full React application with biometric authentication:
import { useBioKey } from 'biokey-react'
import { useState } from 'react'
import './App.css'

function App() {
  const { 
    identity, 
    status, 
    error, 
    isEnrolled, 
    isLoading,
    enroll, 
    authenticate, 
    reset 
  } = useBioKey({
    rpName: 'My React App',
    rpId: window.location.hostname
  })

  const [userId, setUserId] = useState('[email protected]')

  const handleEnroll = async () => {
    try {
      await enroll(userId)
      console.log('Enrollment successful!')
    } catch (err) {
      console.error('Enrollment failed:', err)
    }
  }

  const handleAuth = async () => {
    try {
      await authenticate(userId)
      console.log('Authentication successful!')
    } catch (err) {
      console.error('Authentication failed:', err)
    }
  }

  const formatKey = (key) => {
    if (!key) return ''
    return key.match(/.{8}/g).join(' ')
  }

  return (
    <div className="app">
      <div className="card">
        <h1>BioKey React Demo</h1>
        
        <div className="status-badge">
          <span className={`badge ${isEnrolled ? 'enrolled' : 'not-enrolled'}`}>
            {isEnrolled ? '✓ Enrolled' : 'Not Enrolled'}
          </span>
          {status !== 'idle' && (
            <span className="status-text">{status}</span>
          )}
        </div>

        {isEnrolled && identity && (
          <div className="identity-display">
            <label>Identity Key</label>
            <code>{formatKey(identity.publicKey)}</code>
            <div className="metadata">
              <small>Method: {identity.method}</small>
              <small>Device: {identity.deviceId}</small>
            </div>
          </div>
        )}

        {error && (
          <div className="error-message">
            {error}
          </div>
        )}

        {!isEnrolled && (
          <div className="input-group">
            <label htmlFor="userId">User ID</label>
            <input
              id="userId"
              type="email"
              value={userId}
              onChange={(e) => setUserId(e.target.value)}
              placeholder="[email protected]"
            />
          </div>
        )}

        <div className="actions">
          {!isEnrolled ? (
            <button 
              onClick={handleEnroll} 
              disabled={isLoading || !userId}
              className="btn btn-primary"
            >
              {isLoading ? 'Waiting for fingerprint...' : 'Enroll'}
            </button>
          ) : (
            <>
              <button 
                onClick={handleAuth} 
                disabled={isLoading}
                className="btn btn-success"
              >
                {isLoading ? 'Authenticating...' : 'Authenticate'}
              </button>
              <button 
                onClick={reset}
                className="btn btn-ghost"
              >
                Reset
              </button>
            </>
          )}
        </div>

        <p className="note">
          Your biometric data never leaves your device.
          <br />
          Requires HTTPS or localhost.
        </p>
      </div>
    </div>
  )
}

export default App

The useBioKey Hook

The useBioKey hook provides a complete interface for biometric authentication:

Hook API

const {
  // State
  identity,      // Current identity object or null
  status,        // 'idle' | 'enrolling' | 'enrolled' | 'authenticating' | 'authenticated' | 'error'
  error,         // Error message if status is 'error'
  isEnrolled,    // Boolean: is user enrolled?
  isLoading,     // Boolean: is an operation in progress?
  
  // Actions
  enroll,        // (userId?) => Promise<identity>
  authenticate,  // (userId?) => Promise<result>
  reset          // () => void - clears enrollment
} = useBioKey(options)

Options

interface BioKeyOptions {
  rpId?: string       // Relying party ID (defaults to hostname)
  rpName?: string     // Relying party name
  serverUrl?: string  // Optional server URL for remote verification
}

Advanced: Login Component

Here’s a more production-ready login component:
LoginForm.jsx
import { useBioKey } from 'biokey-react'
import { useState } from 'react'

export function LoginForm({ onSuccess }) {
  const [email, setEmail] = useState('')
  const { isEnrolled, isLoading, error, enroll, authenticate } = useBioKey()

  const handleSubmit = async (e) => {
    e.preventDefault()
    
    try {
      if (isEnrolled) {
        // Authenticate existing user
        const result = await authenticate(email)
        onSuccess({ email, verified: true, ...result })
      } else {
        // Enroll new user
        const result = await enroll(email)
        onSuccess({ email, enrolled: true, ...result })
      }
    } catch (err) {
      console.error('Login failed:', err)
    }
  }

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        placeholder="Enter your email"
        required
      />
      
      {error && <div className="error">{error}</div>}
      
      <button type="submit" disabled={isLoading || !email}>
        {isLoading ? (
          'Waiting for biometric...'
        ) : isEnrolled ? (
          'Sign In with Biometric'
        ) : (
          'Enroll Biometric'
        )}
      </button>
    </form>
  )
}

Running the Example

1

Create Project

npm create vite@latest biokey-demo -- --template react
cd biokey-demo
2

Install Dependencies

npm install biokey-react biokey-js
3

Copy Code

Replace App.jsx and App.css with the code above.
4

Run Dev Server

npm run dev
HTTPS Required: WebAuthn only works on localhost or HTTPS origins. When deploying, ensure your site uses HTTPS.

State Management

The hook manages state automatically, but you can also integrate with external state:
Using Context
import { createContext, useContext } from 'react'
import { useBioKey } from 'biokey-react'

const AuthContext = createContext(null)

export function AuthProvider({ children }) {
  const biokey = useBioKey({ rpName: 'My App' })
  
  return (
    <AuthContext.Provider value={biokey}>
      {children}
    </AuthContext.Provider>
  )
}

export function useAuth() {
  const context = useContext(AuthContext)
  if (!context) throw new Error('useAuth must be used within AuthProvider')
  return context
}
Then use it anywhere:
function ProfileButton() {
  const { isEnrolled, authenticate } = useAuth()
  
  return (
    <button onClick={() => authenticate()}>
      {isEnrolled ? 'Verify Identity' : 'Set Up Biometric'}
    </button>
  )
}

TypeScript Support

The hook is fully typed. Install type definitions:
npm install -D @types/webauthn
Use with TypeScript:
import { useBioKey } from 'biokey-react'
import type { BioKeyIdentity } from 'biokey-js'

function App() {
  const { identity, enroll, authenticate } = useBioKey()
  
  const handleEnroll = async (): Promise<void> => {
    const result: BioKeyIdentity = await enroll('[email protected]')
    console.log('Enrolled:', result.publicKey)
  }
  
  // ...
}

Next Steps

Full-Stack Example

Add server-side verification and user management

API Reference

Complete API documentation for useBioKey

Build docs developers (and LLMs) love