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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@productiongrade/passkeys

v1.1.1

Published

Production-ready passkey authentication library for Node.js applications

Readme

@productiongrade/passkeys

Production-ready passkey authentication library for Node.js applications.

npm version TypeScript Test Coverage License: MIT Node.js

Why Passkeys?

Passkeys provide passwordless authentication using device biometrics (Face ID, Touch ID, Windows Hello) or security keys. Benefits include:

  • More Secure: No passwords to steal, phish, or leak
  • Faster UX: Biometric auth in seconds, no typing
  • Lower Costs: Eliminate password reset support tickets
  • Standards-Based: WebAuthn/FIDO2 supported across all major browsers
  • Cross-Device: Works on phones, laptops, tablets, and security keys

Features

Core Capabilities

  • WebAuthn/FIDO2 Compliant - Standards-based passkey authentication
  • Next.js 14+ Adapter - App Router integration with 10-20 lines of code
  • Express Integration - Ready-to-use Express adapter with RFC 7807 error handling
  • NextAuth Provider - Seamless NextAuth credentials provider for session management
  • React Hooks - usePasskeyRegistration, usePasskeyAuth, usePasskeyManagement
  • Framework-Agnostic Core - Bring your own framework
  • Flexible Storage - Use any database via storage interface
  • TypeScript-First - 100% type-safe with full IntelliSense support

Security Features

  • Counter Anomaly Detection - Detects cloned credentials
  • Challenge-Based Auth - Replay attack prevention (5-min TTL)
  • Recovery Mechanisms - Bcrypt-hashed recovery codes + email recovery
  • Security Event Hooks - Monitor all authentication events
  • User Verification - Configurable biometric requirements

Developer Experience

  • 30-Minute Integration - Get started in minutes
  • Reference Implementations - Prisma (PostgreSQL) + Redis adapters included
  • Comprehensive Docs - API reference, migration guides, troubleshooting
  • 93%+ Test Coverage - Production-ready quality with 160+ tests
  • Testing Utilities - Mock storage and fixtures for easy testing
  • Type-Safe Error Handling - Type guards and enhanced error messages
  • Configuration Validation - Catch config errors early with helpful messages
  • Active Maintenance - Built and maintained by ProductionGrade

Installation

npm install @productiongrade/passkeys

Peer Dependencies

# For Next.js integration
npm install next next-auth  # Optional: next-auth only if using PasskeyProvider

# For Express integration
npm install express

# For React hooks
npm install react @simplewebauthn/browser

Quick Start

Next.js 14+ (App Router)

// app/api/auth/passkeys/[[...passkey]]/route.ts
import { createNextPasskeys } from '@productiongrade/passkeys/nextjs';
import { PrismaAdapter } from '@productiongrade/passkeys/adapters/prisma';
import { prisma } from '@/lib/prisma';

const { POST, GET, DELETE, PATCH } = createNextPasskeys({
  rpId: process.env.NEXT_PUBLIC_RP_ID!,
  rpName: 'My App',
  origin: process.env.NEXT_PUBLIC_APP_URL!,
  storage: new PrismaAdapter(prisma),
});

export { POST, GET, DELETE, PATCH };

With NextAuth Integration:

// app/api/auth/[...nextauth]/route.ts
import NextAuth from 'next-auth';
import { PasskeyProvider } from '@productiongrade/passkeys/nextjs/provider';
import { storage } from '@/lib/storage';

const handler = NextAuth({
  providers: [
    PasskeyProvider({
      rpId: process.env.NEXT_PUBLIC_RP_ID!,
      rpName: 'My App',
      origin: process.env.NEXT_PUBLIC_APP_URL!,
      storage,
    }),
  ],
});

export { handler as GET, handler as POST };

Express

import express from 'express';
import { createPasskeys } from '@productiongrade/passkeys/express';
import { MemoryStorage, MemoryChallengeStorage } from '@productiongrade/passkeys/adapters/memory';

const app = express();
app.use(express.json());

// Create passkey authentication
const { router, middleware } = createPasskeys({
  rpId: 'localhost',                      // Your domain
  rpName: 'My App',                       // Your app name
  origin: 'http://localhost:3000',        // Your origin
  storage: new MemoryStorage(),           // User/passkey storage
  challengeStorage: new MemoryChallengeStorage(), // Challenge storage
  recovery: {
    email: {
      enabled: true,
      sendEmail: async (to, token) => {
        // Send recovery email
        console.log(`Recovery token for ${to}: ${token}`);
      }
    }
  },
  hooks: {
    onAuthSuccess: async (userId) => {
      console.log('User authenticated:', userId);
    }
  }
});

// Mount authentication routes
app.use('/api/auth', router);

// Protected route example
app.get('/api/profile', middleware.requireAuth, (req, res) => {
  res.json({ user: req.user });
});

app.listen(3000, () => {
  console.log('Server running on http://localhost:3000');
});

React Integration

import { usePasskeyAuth } from '@productiongrade/passkeys/react';

function LoginForm() {
  const { authenticate, isLoading, error } = usePasskeyAuth({
    apiUrl: '/api/auth',
    onSuccess: (user) => {
      console.log('Logged in:', user);
      navigate('/dashboard');
    },
  });

  return (
    <button onClick={() => authenticate('[email protected]')} disabled={isLoading}>
      {isLoading ? 'Authenticating...' : 'Sign in with Passkey'}
    </button>
  );
}

Available Hooks:

  • usePasskeyRegistration() - Passkey registration flow
  • usePasskeyAuth() - Authentication flow
  • usePasskeyManagement() - List/update/delete passkeys

See react-integration.mdx for complete React documentation.

Documentation

Getting Started

  • Getting Started - Quick setup guide for all frameworks
  • Concepts - Understanding passkeys, WebAuthn, and architecture
  • Examples - Common patterns and copy-paste code samples

Reference

Guides

  • Best Practices - Security, performance, and production recommendations
  • Deployment - Production deployment checklist and setup
  • Testing - Testing strategies, patterns, and utilities
  • Error Handling - Error types, handling patterns, and recovery
  • Patterns - Real-world patterns (multi-tenant, RBAC, sessions, etc.)

Framework Integration

Storage Adapters

Use any database by implementing the PasskeyStorage interface:

import { PrismaAdapter } from '@productiongrade/passkeys/adapters/prisma';
import { RedisChallengeStorage } from '@productiongrade/passkeys/adapters/redis';
import prisma from './prisma';
import redis from './redis';

const { router } = createPasskeys({
  rpId: 'example.com',
  rpName: 'My App',
  origin: 'https://example.com',
  storage: new PrismaAdapter(prisma),           // PostgreSQL via Prisma
  challengeStorage: new RedisChallengeStorage(redis), // Redis for challenges
});

Included Adapters:

  • MemoryStorage - In-memory (development only)
  • PrismaAdapter - PostgreSQL, MySQL, SQLite via Prisma
  • RedisChallengeStorage - Redis for ephemeral challenges

Custom Adapters: See storage-adapters.mdx for implementing your own storage adapter.

Examples

React Full-Stack Example

examples/react-fullstack-app/ - Complete working application

A production-ready example demonstrating:

  • Passkey registration and authentication
  • React hooks (usePasskeyRegistration, usePasskeyAuth, usePasskeyManagement)
  • Express backend with session management
  • Responsive, modern UI
  • TypeScript throughout
cd examples/react-fullstack-app
npm install
npm run dev

Open http://localhost:5173 to see it in action!

Basic Express Example

examples/basic-express-app.ts - Minimal Express server

npm run build
npx ts-node examples/basic-express-app.ts

Developer Utilities

Type-Safe Error Handling

import { isAuthenticationError, getErrorDetails } from '@productiongrade/passkeys';

try {
  await passkeyService.authenticate(...);
} catch (error) {
  if (isAuthenticationError(error)) {
    const details = getErrorDetails(error);
    if (details?.details?.troubleshooting) {
      console.log('Help:', details.details.troubleshooting);
    }
  }
}

Configuration Validation

import { validatePasskeyConfig, createPasskeyConfig } from '@productiongrade/passkeys';

// Validate config at startup
const result = validatePasskeyConfig(config);
if (!result.valid) {
  console.error('Errors:', result.errors);
}

// Or use builder with defaults
const config = createPasskeyConfig({
  rpId: 'example.com',
  rpName: 'My App',
  origin: 'https://example.com',
  storage: myStorage,
  challenges: myChallengeStorage,
});

Testing Utilities

import { createMockStorage, testFixtures } from '@productiongrade/passkeys/testing';

const storage = createMockStorage();
const user = testFixtures.createTestUser({ email: '[email protected]' });

Debug Mode

import { debugLog } from '@productiongrade/passkeys';

// Set DEBUG=@productiongrade/passkeys:* to enable
debugLog('PasskeyService', 'Starting registration', { userId, email });

See api-reference.mdx for complete utility documentation.

Testing

# Run all tests (160+ tests, 93%+ coverage)
npm test

# Watch mode for development
npm run test:watch

# Generate coverage report
npm run test:coverage

# Test API endpoints
chmod +x examples/test-api.sh
./examples/test-api.sh

Test Coverage:

  • Unit tests for all core services
  • Integration tests for complete authentication flows
  • Contract tests for storage implementations
  • Real WebAuthn testing with HTTPS

See TESTING.md for detailed testing instructions.

Architecture

  • Framework-agnostic core - works with any Node.js framework
  • Storage interface pattern - works with any database
  • Express adapter - ready-to-use Express integration
  • React hooks - optional frontend utilities
  • Reference implementations - Prisma, Redis, in-memory examples

Requirements

  • Node.js 18+ (LTS)
  • TypeScript 5.3+ (recommended)

Security

This library implements WebAuthn/FIDO2 standards with enterprise-grade security:

Authentication Security

  • Challenge-based authentication (5-minute TTL, single-use)
  • Origin validation (prevents phishing attacks)
  • Counter anomaly detection (detects cloned credentials)
  • User verification support (biometric/PIN requirements)

Data Security

  • Bcrypt-hashed recovery codes (10 rounds)
  • SHA-256 hashed email recovery tokens
  • No plaintext secrets ever stored
  • Automatic challenge cleanup

Monitoring & Compliance

  • Security event hooks for all authentication events
  • Counter anomaly alerts
  • Failed authentication tracking
  • RFC 7807 Problem Details error responses

Example: Security Monitoring

const { router } = createPasskeys({
  // ... config
  hooks: {
    onAuthFailure: async (email, error) => {
      await securityLog.create({
        type: 'AUTH_FAILURE',
        email,
        error: error.message,
      });
    },
    onCounterAnomaly: async (userId, passkeyId, expected, received) => {
      await alerts.send('CRITICAL: Possible cloned credential', {
        userId,
        passkeyId,
        expected,
        received,
      });
      // Lock account pending investigation
      await accounts.lock(userId);
    },
  },
});

Contributing

We welcome contributions! See CONTRIBUTING.md for:

  • Development setup
  • Code standards
  • Testing requirements
  • Pull request process

Changelog

See CHANGELOG.md for release history.

License

MIT © ProductionGrade

Support

Getting Help

Resources

Roadmap

Future enhancements:

  • Fastify adapter
  • Vue.js composables
  • Svelte stores
  • MongoDB adapter
  • MySQL/PostgreSQL adapters (non-Prisma)
  • Enhanced audit logging

Built by ProductionGrade


Stay Ahead on Production grade Security, Engineering and AI Governance

I write weekly technical breakdowns for engineering leaders — covering security, infrastructure, and AI governance. No fluff. Just what works in production.