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

@thru/passkey

v0.2.7

Published

Browser-only WebAuthn package for passkey registration, signing, and popup-based flows. Built on top of `@thru/passkey-manager` for platform-agnostic crypto and encoding utilities.

Downloads

568

Readme

@thru/passkey

Browser-only WebAuthn package for passkey registration, signing, and popup-based flows. Built on top of @thru/passkey-manager for platform-agnostic crypto and encoding utilities.

Installation

npm install @thru/passkey

This package requires a browser environment with WebAuthn support (navigator.credentials).

Basic Usage

Register a Passkey

Create a new P-256 credential bound to the user's platform authenticator:

import { registerPasskey } from '@thru/passkey';

const result = await registerPasskey('alice', 'user-id-123', 'example.com');
// result.credentialId  - base64url credential ID
// result.publicKeyX    - hex-encoded P-256 X coordinate
// result.publicKeyY    - hex-encoded P-256 Y coordinate
// result.rpId          - relying party ID

Sign with a Known Credential

Sign a challenge using a specific credential ID:

import { signWithPasskey } from '@thru/passkey';

const challenge = new Uint8Array(32); // your challenge bytes
const result = await signWithPasskey(credentialId, challenge, 'example.com');
// result.signature         - 64-byte concatenated r||s (low-S normalized)
// result.signatureR        - 32-byte r component
// result.signatureS        - 32-byte s component
// result.authenticatorData - raw authenticator data
// result.clientDataJSON    - raw client data JSON

Sign with a Stored Passkey

For embedded or iframe contexts where you have stored passkey metadata. Automatically falls back to a popup window when inline WebAuthn is restricted:

import { signWithStoredPasskey } from '@thru/passkey';
import type { PasskeyMetadata } from '@thru/passkey';

const result = await signWithStoredPasskey(
  challenge,
  'example.com',
  preferredPasskey,  // PasskeyMetadata | null
  allPasskeys,       // PasskeyMetadata[]
  { appName: 'My App', origin: 'https://app.example.com' }
);
// result includes .passkey metadata for the credential that signed

Sign with a Discoverable Passkey

Let the browser prompt the user to choose from their available passkeys:

import { signWithDiscoverablePasskey } from '@thru/passkey';

const result = await signWithDiscoverablePasskey(challenge, 'example.com');
// result.credentialId - the credential the user selected
// result.rpId         - relying party ID

Key Capabilities

  • P-256 (ES256) credential creation via navigator.credentials.create with platform authenticator selection, resident key, and user verification required
  • Three signing modes: known credential, stored passkey with fallback, and discoverable (browser-prompted)
  • Automatic popup fallback for iframe/embedded contexts where the Permissions Policy blocks inline WebAuthn
  • Low-S signature normalization applied to all signing results for protocol compatibility
  • Capability detection to query WebAuthn support, client capabilities, and determine the optimal prompt mode before signing
  • Re-exports encoding and crypto utilities from @thru/passkey-manager for backward compatibility

Capability Detection

Check browser support and determine the best prompt mode ahead of time:

import {
  isWebAuthnSupported,
  preloadPasskeyClientCapabilities,
  getPasskeyClientCapabilities,
  shouldUsePasskeyPopup,
  isInIframe,
} from '@thru/passkey';

// Quick synchronous check
if (!isWebAuthnSupported()) {
  // WebAuthn not available
}

// Preload capabilities early (e.g., on app init)
preloadPasskeyClientCapabilities();

// Later, read cached or await capabilities
const capabilities = await getPasskeyClientCapabilities();

// Check if a popup is needed for a given action
const needsPopup = await shouldUsePasskeyPopup('get');

Popup Bridge

For applications that host the passkey popup window (e.g., the wallet app), the package provides both the parent-side and popup-side APIs:

Parent Side

import {
  openPasskeyPopupWindow,
  requestPasskeyPopup,
  closePopup,
  PASSKEY_POPUP_PATH,
  PASSKEY_POPUP_CHANNEL,
} from '@thru/passkey';

Popup Window Side

import {
  toPopupSigningResult,
  buildSuccessResponse,
  decodeChallenge,
  getPopupDisplayInfo,
  getResponseError,
  signWithPreferredPasskey,
  buildStoredPasskeyResult,
} from '@thru/passkey';

Communication between parent and popup uses postMessage with BroadcastChannel as a fallback. The popup path defaults to /passkey/popup.

Re-exported Utilities

The following are re-exported from @thru/passkey-manager for convenience:

Crypto: parseDerSignature, normalizeLowS, normalizeSignatureComponent, P256_N, P256_HALF_N, bytesToBigIntBE, bigIntToBytesBE

Encoding: arrayBufferToBase64Url, base64UrlToArrayBuffer, bytesToBase64Url, base64UrlToBytes, bytesToHex, hexToBytes, bytesEqual, compareBytes, uniqueAccounts

Types

Key types exported from this package:

| Type | Description | |------|-------------| | PasskeyRegistrationResult | Credential ID and P-256 public key coordinates | | PasskeySigningResult | Signature bytes, authenticator data, and client data | | PasskeyDiscoverableSigningResult | Signing result with credential ID and rpId | | PasskeyStoredSigningResult | Signing result with attached passkey metadata | | PasskeyMetadata | Stored passkey info (credential ID, public key, rpId, timestamps) | | PasskeyClientCapabilities | WebAuthn client capability flags | | PasskeyPopupContext | App context passed to popup for display | | PasskeyPopupAccount | Account info passed through popup bridge |