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

webauthn-authenticator

v0.0.2-alpha.1

Published

A standalone TypeScript library for mocking WebAuthn in browsers, particularly useful for Playwright testing and headless browser automation

Readme

WebAuthn Authenticator Standalone

A standalone TypeScript library for mocking WebAuthn in browsers, particularly useful for Playwright testing and headless browser automation.

Features

  • Complete WebAuthn Mock: Replaces navigator.credentials.create and navigator.credentials.get with in-memory implementations
  • ES256/P-256 Support: Full support for ECDSA with SHA-256 cryptographic operations
  • Request Queue Management: New modular architecture with pending request control for advanced testing scenarios
  • Test Control: Fine-grained control over request approval, rejection, and timeouts
  • Playwright Integration: Designed to work seamlessly with Playwright test fixtures
  • Modern TypeScript: Built with Vite, includes TypeScript definitions
  • Browser Compatible: Runs in modern browsers with proper polyfills

Architecture

The library has been refactored into a modular architecture:

  • Authenticator: Main facade implementing navigator.credentials API
  • RequestManager: Manages queued requests with test control capabilities
  • CredentialStore: Handles credential storage and retrieval
  • CryptoEngine: Performs all cryptographic operations
  • PendingRequest: Individual request objects with approval/rejection control

Quick Start

Installation

npm install

Development

# Start development server with demo
npm run dev

# Run unit tests
npm test

# Run Playwright tests
npm run playwright

# Build the library
npm run build:lib

Demo Application

The project includes a demo application that showcases the WebAuthn authenticator in action. Visit the development server to see:

  • Creating WebAuthn credentials
  • Retrieving existing credentials
  • Managing multiple credentials
  • Different relying party ID handling

Usage

Request-Based API

The architecture provides fine-grained control over WebAuthn requests for advanced testing scenarios:

import { Authenticator, RequestManager, CredentialStore, CryptoEngine, installWebAuthnMock } from 'webauthn-authenticator'

// Create modules
const credentialStore = new CredentialStore()
const cryptoEngine = new CryptoEngine()
const requestManager = new RequestManager(credentialStore, cryptoEngine)
const authenticator = new Authenticator(requestManager)

// In your test setup (e.g., Playwright)
await context.exposeFunction('createCredential', (options) => 
  authenticator.create(options)
)
await context.exposeFunction('getCredential', (options) => 
  authenticator.get(options)
)

// Install the WebAuthn mock
await context.addInitScript(() => {
  installWebAuthnMock({
    exposedCreateCredFuncName: 'createCredential',
    exposedGetCredFuncName: 'getCredential'
  })
})

// In your test - control request flow
test('should create credential with user approval', async ({ page }) => {
  // Start credential creation (won't complete until approved)
  const createPromise = page.evaluate(() => {
    return navigator.credentials.create({ publicKey: options })
  })

  // Get the pending request
  const pendingRequest = await authenticator.requestManager.waitForNextRequest()
  expect(pendingRequest.type).toBe('create')

  // Approve the request
  await pendingRequest.approve({ userVerification: true })

  // Now the browser promise resolves
  const credential = await createPromise
  expect(credential).toBeDefined()
})

// Simulate user rejection
test('should handle user cancellation', async ({ page }) => {
  const createPromise = page.evaluate(() => {
    return navigator.credentials.create({ publicKey: options })
  })

  const request = await authenticator.requestManager.waitForNextRequest()
  await request.reject(new DOMException('User cancelled', 'NotAllowedError'))

  await expect(createPromise).rejects.toThrow('User cancelled')
})

Browser Integration

import { Authenticator, RequestManager, CredentialStore, CryptoEngine, installWebAuthnMock } from 'webauthn-authenticator'

// Create the modular authenticator
const credentialStore = new CredentialStore()
const cryptoEngine = new CryptoEngine()
const requestManager = new RequestManager(credentialStore, cryptoEngine)
const authenticator = new Authenticator(requestManager)

// Expose functions to browser window
window.createCredential = authenticator.create.bind(authenticator)
window.getCredential = authenticator.get.bind(authenticator)

// Install the WebAuthn mock
installWebAuthnMock({
  exposedCreateCredFuncName: 'createCredential',
  exposedGetCredFuncName: 'getCredential'
})

// Now navigator.credentials.create() and navigator.credentials.get() work!
// But they create pending requests that need manual approval

Playwright Test Integration

import { test as base } from '@playwright/test'
import { Authenticator } from 'webauthn-authenticator'

const test = base.extend<{ authenticator: Authenticator }>({
  authenticator: async ({}, use) => {
    const authenticator = new Authenticator()
    await use(authenticator)
  },
  
  context: async ({ context, authenticator }, use) => {
    // Expose authenticator functions
    await context.exposeFunction('createCredential', 
      authenticator.createPublicKeyCredential.bind(authenticator))
    await context.exposeFunction('getCredential', 
      authenticator.getPublicKeyCredential.bind(authenticator))
    
    // Add preload script
    await context.addInitScript(() => {
      // Install WebAuthn mock (include the installWebAuthnMock code here)
    })
    
    await use(context)
  }
})

test('should create WebAuthn credential', async ({ page, authenticator }) => {
  // Your test code here - navigator.credentials.create() will work!
})

API Reference

Authenticator Class

Methods

  • createPublicKeyCredential(options) - Creates a new WebAuthn credential
  • getPublicKeyCredential(options) - Retrieves an existing credential
  • cancelNextOperation() - Cancels the next create/get operation (throws NotAllowedError)

Properties

  • credentials - Object containing all created credentials keyed by credential ID

Utility Functions

  • installWebAuthnMock(options) - Installs the WebAuthn mock in browser
  • deserializePublicKeyCredentialAttestion(credential) - Converts serialized attestation to browser format
  • deserializePublicKeyCredentialAssertion(credential) - Converts serialized assertion to browser format

Architecture

This library is based on the WebAuthn authenticator from the SendApp monorepo, specifically the @0xsend/webauthn-authenticator package. It has been extracted and modernized as a standalone library.

Key Components

  1. Authenticator: Core class that manages credential lifecycle and cryptographic operations
  2. Preload Script: Browser-side code that replaces the native WebAuthn API
  3. Type Definitions: Complete TypeScript definitions for WebAuthn operations
  4. Utilities: Helper functions for serialization and browser compatibility

Cryptographic Implementation

  • Uses Node.js crypto module for key generation and signing
  • Implements ECDSA with P-256 curve (ES256)
  • Generates proper CBOR-encoded attestation objects
  • Supports signature counters and authenticator data

Testing

The project includes comprehensive tests:

  • Unit Tests (Vitest): Test core authenticator functionality
  • Integration Tests (Playwright): Test browser integration and WebAuthn API mocking
  • Demo Tests: Validate the demo application works correctly

Building

# Build library for distribution
npm run build:lib

# Build demo application
npm run build

License

This project is derived from the SendApp monorepo and maintains compatibility with its WebAuthn implementation.

Contributing

This is a workspace for developing a standalone version of the SendApp WebAuthn authenticator. When contributing:

  1. Maintain compatibility with the original SendApp implementation
  2. Follow TypeScript best practices
  3. Include tests for new features
  4. Update documentation as needed

Troubleshooting

Common Issues

  1. Import Errors: Make sure all dependencies are installed and TypeScript is configured correctly
  2. Crypto Warnings: The "externalized for browser compatibility" warning is expected for Node.js crypto usage
  3. Test Timeouts: Ensure the development server is running for Playwright tests

Browser Compatibility

The library requires modern browsers with support for:

  • WebCrypto API
  • ArrayBuffer/TypedArrays
  • ES2020+ features# Test commit to trigger CI/CD with updated permissions