npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

capacitor-biometric-authentication

v2.3.1

Published

Framework-agnostic biometric authentication library. Works with React, Vue, Angular, or vanilla JS. No providers required!

Readme

Biometric Authentication

A framework-agnostic biometric authentication library for React, Vue, Angular, or vanilla JavaScript. No providers required!

npm version License: MIT

Links

Current State

  • Package version: 2.3.0
  • Tests: 71/71 passing via the test script in the last verification pass
  • Build: the build script succeeds in the last verification pass
  • Runtime coverage in package architecture:
    • WebAuthn via the web adapter, returning a server-verifiable webAuthnResponse
    • Capacitor native support for iOS and Android
    • Electron adapter included in source
    • Shared core/state logic for framework-agnostic usage

Features

  • Zero Dependencies - Works without any specific framework (Capacitor optional)
  • Provider-less - Direct API like Zustand, no Context/Providers needed
  • Multi-Platform - Web (WebAuthn), iOS, Android, Electron support
  • Framework Agnostic - Works with React, Vue, Angular, Vanilla JS
  • TypeScript First - Full type safety and IntelliSense
  • Server-verifiable on web - Returns the standard WebAuthn JSON for relying-party verification
  • Hardware-backed secure storage - Android Keystore, iOS Secure Enclave + Keychain, platform authenticators on web
  • Tiny Bundle - Tree-shakeable with dynamic imports
  • Backward Compatible - Works as a Capacitor plugin too

Security model: A successful authentication (result.success === true) means the local biometric / WebAuthn ceremony completed. On its own it is not proof of identity. On web, send result.webAuthnResponse to your relying-party server (for example webauthn-server-buildkit) and verify it against the challenge the server issued. isAuthenticated() and the client session are a UX gate, not a security boundary. See Security Best Practices.

Installation

yarn add capacitor-biometric-authentication

Package Manager Policy

  • Use yarn for project-local installs and script execution.
  • Use pnpm for global package installs.
  • Use npm only to install or update pnpm globally.
  • Keep yarn.lock and remove other lockfiles.

Quick Start

import BiometricAuth from 'capacitor-biometric-authentication';

// Check availability (resolves to a boolean)
const available = await BiometricAuth.isAvailable();

// Run the biometric / WebAuthn ceremony. authenticate() never throws —
// inspect result.success and result.error instead.
const result = await BiometricAuth.authenticate({
  reason: 'Please authenticate to continue',
});

if (result.success) {
  // On web, result.webAuthnResponse is the standard WebAuthn JSON.
  // Send it to your server to VERIFY before trusting the user's identity.
  console.log('Local ceremony completed', result.webAuthnCeremony);
} else {
  console.log('Failed:', result.error?.code, result.error?.message);
}

Verified Package Architecture

  • src/core/ contains the shared biometric auth orchestration and platform detection logic.
  • src/adapters/ contains Web (WebAuthn), Capacitor, and Electron adapters.
  • src/types/ is the canonical type source, including the webAuthnResponse shapes used for server verification.
  • src/utils/ contains session, encoding, and error utilities.
  • android/ and ios/ contain native plugin implementations.
  • tests/ currently covers encoding and error-handling utilities with Vitest (71 tests).

Verification Commands

yarn test
yarn build

Production Integration Guide

This section provides step-by-step instructions for integrating this plugin into a production Capacitor app.

Prerequisites

  • Node.js >=18.0.0
  • Capacitor 8.x (@capacitor/core ^8.0.1 peer dependency; optional — the web adapter works without Capacitor)
  • For iOS: Xcode 15+, CocoaPods
  • For Android: Android Studio, JDK 17

Step 1: Install the Plugin

yarn add capacitor-biometric-authentication

Step 2: Sync Native Projects

npx cap sync

Step 3: Platform-Specific Configuration

Android Configuration

Minimum Requirements:

  • minSdkVersion: 23 (Android 6.0)
  • compileSdkVersion: 35
  • Java 17

The plugin automatically includes required permissions in its AndroidManifest.xml:

<uses-permission android:name="android.permission.USE_BIOMETRIC" />

Verify Gradle Settings (android/app/build.gradle):

android {
    compileSdkVersion 35

    defaultConfig {
        minSdkVersion 23
        targetSdkVersion 35
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17
        targetCompatibility JavaVersion.VERSION_17
    }
}

iOS Configuration

Minimum Requirements:

  • iOS 13.0+
  • Swift 5.1+

Required Info.plist Entry:

Add to ios/App/App/Info.plist:

<key>NSFaceIDUsageDescription</key>
<string>We use Face ID to securely authenticate you</string>

Note: This key is required for Face ID devices. Without it, your app will crash when attempting Face ID authentication.

Web Configuration

Requirements:

  • HTTPS (or localhost for development)
  • Browser with WebAuthn support (Chrome 67+, Safari 14+, Firefox 60+, Edge 79+)
  • Platform authenticator (TouchID, Windows Hello, etc.)

Development:

yarn dev  # localhost works without HTTPS

Production: Ensure your site uses HTTPS. WebAuthn will not work on non-secure origins.

Step 4: Use the Plugin

import BiometricAuth from 'capacitor-biometric-authentication';

// Check if biometrics are available
const available = await BiometricAuth.isAvailable();

if (available) {
  // Configure session duration (in seconds)
  BiometricAuth.configure({
    sessionDuration: 3600, // 1 hour
  });

  // Authenticate
  const result = await BiometricAuth.authenticate({
    reason: 'Authenticate to access your account',
    fallbackTitle: 'Use Passcode',
  });

  if (result.success) {
    console.log('Authenticated!');
  } else {
    console.error('Auth failed:', result.error?.message);
  }
}

Step 5: Build and Run

Web:

yarn build
yarn preview

Android:

npx cap sync android
npx cap run android
# or open in Android Studio:
npx cap open android

iOS:

npx cap sync ios
cd ios && pod install && cd ..
npx cap run ios
# or open in Xcode:
npx cap open ios

Framework Examples

React Example

import { useState, useEffect } from 'react';
import BiometricAuth from 'capacitor-biometric-authentication';

function SecureComponent() {
  const [isAuthenticated, setIsAuthenticated] = useState(false);

  useEffect(() => {
    const unsubscribe = BiometricAuth.subscribe((state) => {
      setIsAuthenticated(state.isAuthenticated);
    });
    return unsubscribe;
  }, []);

  const handleLogin = async () => {
    const result = await BiometricAuth.authenticate({
      reason: 'Access your account',
    });
    if (!result.success) console.error('Auth failed:', result.error);
  };

  return isAuthenticated ? (
    <h1>Welcome back!</h1>
  ) : (
    <button onClick={handleLogin}>Login with Biometrics</button>
  );
}

Vue Example

<template>
  <button
    v-if="!isAuthenticated"
    @click="authenticate"
  >
    Login with Biometrics
  </button>
  <div v-else>Welcome back!</div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import BiometricAuth from 'capacitor-biometric-authentication';

const isAuthenticated = ref(false);
let unsubscribe;

onMounted(() => {
  unsubscribe = BiometricAuth.subscribe((state) => {
    isAuthenticated.value = state.isAuthenticated;
  });
});

onUnmounted(() => unsubscribe?.());

const authenticate = () =>
  BiometricAuth.authenticate({ reason: 'Access your account' });
</script>

Vanilla JavaScript

<script type="module">
  import BiometricAuth from 'https://unpkg.com/capacitor-biometric-authentication/dist/web.js';

  document.getElementById('auth-btn').addEventListener('click', async () => {
    const result = await BiometricAuth.authenticate({
      reason: 'Please authenticate',
    });
    if (result.success)
      document.getElementById('status').textContent = 'Authenticated!';
  });
</script>
<button id="auth-btn">Authenticate</button>
<div id="status"></div>

API Reference

Core Methods

| Method | Returns | Description | | -------------------------- | -------------------------------- | --------------------------------------------------------------- | | configure(config) | void | Set plugin configuration (adapter, session duration, debug) | | isAvailable() | Promise<boolean> | Check if biometric auth is available | | getSupportedBiometrics() | Promise<BiometryType[]> | Get available biometric types | | authenticate(options?) | Promise<BiometricAuthResult> | Run the ceremony; resolves with { success, error?, webAuthnResponse? } (never throws) | | deleteCredentials() | Promise<void> | Clear stored credentials and end the session | | hasCredentials() | Promise<boolean> | Whether a credential is stored on this device | | logout() | void | Clear the local authentication session |

State Management

| Method | Returns | Description | | --------------------- | ------------------------ | -------------------------------------------------------------------------- | | subscribe(callback) | () => void | Subscribe to auth-state changes; returns an unsubscribe function | | getState() | BiometricAuthState | Get a snapshot of the current local auth state | | isAuthenticated() | boolean | Whether the local session is still valid — a UX gate, not a security boundary |

Utility Methods

| Method | Returns | Description | | ------------------------------------------- | --------------------- | ------------------------------------------------------------ | | requireAuthentication(callback, options?) | Promise<void> | Authenticate (if not already) then run callback | | withAuthentication(callback, options?) | Promise<T> | Authenticate (if not already) then run callback and return its value | | registerAdapter(name, adapter) | void | Register a custom platform adapter (advanced) |

Configuration Options

BiometricAuth.configure({
  adapter: 'auto', // 'auto' | 'web' | 'capacitor' | 'electron' | custom name
  sessionDuration: 3600, // Local session duration in SECONDS (default: 3600)
  debug: false, // Enable debug logging
});

configure() returns void (it is not async).

Authentication Options

await BiometricAuth.authenticate({
  reason: 'Authentication Required', // Displayed to user
  title: 'Biometric Login', // Android dialog title
  subtitle: 'Log in to your account', // Android dialog subtitle
  fallbackTitle: 'Use Passcode', // Fallback button text
  cancelTitle: 'Cancel', // Cancel button text
  disableDeviceCredential: false, // Disable passcode fallback
  maxAttempts: 3, // Max failed attempts before lockout
  // Web only: pass the server-issued challenge so the response can be verified.
  platform: {
    web: { challenge: serverChallenge, userVerification: 'required' },
  },
});

On web, userVerification defaults to 'required' and a secure context (HTTPS or localhost) is mandatory — otherwise authenticate() resolves with error.code === 'INSECURE_CONTEXT'. See the Web Platform Guide and WebAuthn Advanced for the full server-verified flow.


Platform Support

| Platform | Technology | Min Version | Status | | ------------------ | ------------------ | ----------- | ------ | | Web | WebAuthn API | Chrome 67+ | ✅ | | iOS | Touch ID / Face ID | iOS 13.0 | ✅ | | Android | BiometricPrompt | API 23 | ✅ | | Electron (macOS) | Touch ID | - | ✅ | | Electron (Windows) | Windows Hello | Windows 10 | ✅ |

Browser Support

  • Chrome/Edge 67+ (Windows Hello, Touch ID)
  • Safari 14+ (Touch ID, Face ID)
  • Firefox 60+ (Windows Hello)

Windows Hello Support (Electron)

The plugin supports Windows Hello on Electron for Windows platforms. When running on Windows (win32), the ElectronAdapter automatically uses the WebAuthn API to interface with Windows Hello.

Requirements:

  • Windows 10 or later
  • Windows Hello configured in Windows Settings
  • Electron with WebAuthn support

Usage: The same API works across all platforms:

// Works on macOS (Touch ID) and Windows (Windows Hello)
const result = await BiometricAuth.authenticate({
  reason: 'Authenticate with Windows Hello',
});

Error Handling

authenticate() resolves rather than throwing; branch on result.error?.code using the canonical BiometricErrorCode values.

import BiometricAuth, {
  BiometricErrorCode,
} from 'capacitor-biometric-authentication';

const result = await BiometricAuth.authenticate();

if (!result.success) {
  switch (result.error?.code) {
    case BiometricErrorCode.USER_CANCELLED:
      console.log('User cancelled');
      break;
    case BiometricErrorCode.AUTHENTICATION_FAILED:
      console.log('Biometric not recognized');
      break;
    case BiometricErrorCode.NOT_AVAILABLE:
      console.log('Biometric not available');
      break;
    case BiometricErrorCode.LOCKED_OUT:
      console.log('Too many failed attempts');
      break;
    case BiometricErrorCode.NOT_ENROLLED:
      console.log('No biometrics enrolled');
      break;
    case BiometricErrorCode.INSECURE_CONTEXT:
      console.log('Web requires HTTPS or localhost');
      break;
    default:
      console.log('Error:', result.error?.code, result.error?.message);
  }
}

The legacy aliases BIOMETRIC_UNAVAILABLE, LOCKOUT, and UNKNOWN_ERROR are deprecated. Adapters now emit only canonical codes — use NOT_AVAILABLE, LOCKED_OUT, and UNKNOWN. See the Error Handling Overview for the full list.


Troubleshooting

For build failures and common integration issues, see the comprehensive Troubleshooting Guide.

Common issues covered:

  • Android Gradle/SDK version mismatches
  • iOS Info.plist missing entries
  • Pod installation failures
  • WebAuthn HTTPS requirements
  • Plugin registration issues

Development

# Install dependencies
yarn install

# Build plugin
yarn build

# Watch mode
yarn watch

# Lint & format
yarn lint
yarn prettier

# Test in example app
cd example
yarn install
yarn dev           # Web development
yarn cap:sync      # Sync native platforms
yarn cap:ios:run   # Run on iOS
yarn cap:android:run  # Run on Android

Project Structure

├── src/                  # TypeScript source
│   ├── index.ts          # Public API entry (default export: BiometricAuth)
│   ├── core/             # Orchestration + platform detection
│   ├── adapters/         # Web (WebAuthn), Capacitor, Electron adapters
│   ├── types/            # Canonical types (incl. webAuthnResponse shapes)
│   └── utils/            # Encoding, error, logger utilities
├── android/              # Android native (BiometricPrompt + Keystore)
├── ios/                  # iOS native (LocalAuthentication + Secure Enclave/Keychain)
├── example/              # React example app
└── docs/                 # Documentation

Plugin Metadata

| Property | Value | | ----------------- | --------------------------------------- | | Package Name | capacitor-biometric-authentication | | Plugin ID | BiometricAuth | | Android Package | com.aoneahsan.capacitor.biometricauth | | iOS Class | BiometricAuthPlugin | | Capacitor Version | 8.x |


Documentation

Full documentation in docs/:

Contributing

See Contributing Guide for details.

Support

Changelog

See CHANGELOG.md for release history.

License

MIT © Ahsan Mahmood