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

webauthx

v0.1.1

Published

<picture> <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/wevm/webauthx/refs/heads/main/.github/banner-dark.svg"> <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/wevm/webau

Downloads

7,031

Readme

Quickprompt

Prompt your agent:

Add passkey authentication to my app using https://raw.githubusercontent.com/wevm/webauthx/refs/heads/main/SKILL.md, and add it to my skills.

Install

npm i webauthx
pnpm i webauthx
bun i webauthx

Usage Walkthrough

Registration (Sign up)

Register a new passkey credential for a user. The server generates a challenge, the client creates the credential, and the server verifies it.

1. Generate Options (Server)

import { Registration } from 'webauthx/server'

app.post('/register/options', async (request) => {
  const { name } = await request.json()

  // Generate a challenge and WebAuthn options for the client.
  const { challenge, options } = Registration.getOptions({
    name,
    rp: { id: 'example.com', name: 'Example' },
  })

  // Persist challenge for verification in the next step.
  await store.storeChallenge(challenge)

  // Send WebAuthn options to the client.
  return Response.json({ options })
})

2. Create Credential (Client)

import { Registration } from 'webauthx/client'

// Fetch WebAuthn options from the server.
const { options } = await fetch('/register/options', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ name: 'alice' }),
}).then((r) => r.json())

// Prompt the user to create a passkey.
const credential = await Registration.create({ options })

// Send the credential to the server for verification.
await fetch('/register/verify', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ credential }),
})

3. Verify Credential (Server)

import { Registration } from 'webauthx/server'

app.post('/register/verify', async (request) => {
  const { credential } = await request.json()

  // Consume the stored challenge (single-use).
  const challenge = await store.consumeChallenge(request)

  // Verify attestation & extract the public key.
  const result = Registration.verify(credential, {
    challenge,
    origin: 'https://example.com',
    rpId: 'example.com',
  })

  // Persist the credential for future authentication.
  await store.storeCredential(result.credential)
})

Authentication (Log in)

Authenticate a returning user with their existing passkey. The server generates a challenge, the client signs it, and the server verifies the signature.

1. Generate Options (Server)

import { Authentication } from 'webauthx/server'

app.post('/auth/options', async (request) => {
  const { credentialId } = await request.json()

  // Generate a challenge and WebAuthn options for the client.
  const { challenge, options } = Authentication.getOptions({
    credentialId,
    rpId: 'example.com',
  })

  // Persist challenge for verification in the next step.
  await store.storeChallenge(challenge)

  // Send WebAuthn options to the client.
  return Response.json({ options })
})

2. Sign Challenge (Client)

import { Authentication } from 'webauthx/client'

// Fetch WebAuthn options from the server.
const { options } = await fetch('/auth/options', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ credentialId }),
}).then((r) => r.json())

// Prompt the user to sign the challenge with their passkey.
const response = await Authentication.sign({ options })

// Send the response to the server for verification.
await fetch('/auth/verify', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ response }),
})

3. Verify Signature (Server)

import { Authentication } from 'webauthx/server'

app.post('/auth/verify', async (request) => {
  const { response } = await request.json()

  // Consume the stored challenge (single-use).
  const challenge = await store.consumeChallenge(request)

  // Look up the stored public key for this credential.
  const credential = await store.getCredential(response.id)

  // Verify the P-256 signature.
  const valid = Authentication.verify(response, {
    challenge,
    publicKey: credential.publicKey,
    origin: 'https://example.com',
    rpId: 'example.com',
  })
})

API Reference

webauthx/client

Authentication.sign

Signs a challenge via navigator.credentials.get. Accepts WebAuthn options from the server and returns a response ready to send back.

Usage
import { Authentication } from 'webauthx/client'

const response = await Authentication.sign({ options })
Parameters

| Parameter | Type | Description | | --- | --- | --- | | getFn | function | Custom credential request function (for testing). | | options | CredentialRequestOptions | WebAuthn options from Authentication.getOptions. |

Return Value

Promise<Authentication.Response>

Response to send to the server.

Registration.create

Creates a new WebAuthn credential via navigator.credentials.create. Accepts WebAuthn options from the server and returns a credential ready to send back.

Usage
import { Registration } from 'webauthx/client'

const credential = await Registration.create({ options })
Parameters

| Parameter | Type | Description | | --- | --- | --- | | createFn | function | Custom credential creation function (for testing). | | options | CredentialCreationOptions | WebAuthn options from Registration.getOptions. |

Return Value

Promise<Registration.Credential>

Credential to send to the server.


webauthx/server

Authentication.getOptions

Generates PublicKeyCredentialRequestOptions for authentication. A random 32-byte challenge is generated if one isn't provided.

Usage
import { Authentication } from 'webauthx/server'

const { challenge, options } = Authentication.getOptions({
  credentialId: storedCredential.id,
  rpId: 'example.com',
})
Parameters

| Parameter | Type | Description | | --- | --- | --- | | challenge | Hex | Optional challenge. A random 32-byte hex value is generated if omitted. | | credentialId | string \| string[] | Credential ID(s) to allow. | | rpId | string | Relying party ID. | | timeout | number | Timeout in milliseconds. | | userVerification | string | User verification requirement. |

Return Value

{ challenge: Hex; options: CredentialRequestOptions }

Challenge to store and the WebAuthn options to send to the client.

Authentication.verify

Verifies an authentication response from the client. Validates the rpIdHash, origin, challenge, and P-256 signature.

Usage
import { Authentication } from 'webauthx/server'

const valid = Authentication.verify(response, {
  challenge,
  publicKey: credential.publicKey,
  origin: 'https://example.com',
  rpId: 'example.com',
})
Parameters

| Parameter | Type | Description | | --- | --- | --- | | options.challenge | Hex | Expected challenge. | | options.origin | string \| string[] | Expected origin(s). | | options.publicKey | Hex | The stored P-256 public key (hex). | | options.rpId | string | Expected relying party ID. | | response | Authentication.Response | The authentication response from the client. |

Return Value

boolean

true if the signature is valid.

Registration.getOptions

Generates PublicKeyCredentialCreationOptions for registration. A random 32-byte challenge is generated if one isn't provided.

Usage
import { Registration } from 'webauthx/server'

const { challenge, options } = Registration.getOptions({
  name: 'alice',
  rp: { id: 'example.com', name: 'Example' },
})
Parameters

| Parameter | Type | Description | | --- | --- | --- | | attestation | string | Attestation conveyance preference. | | authenticatorSelection | object | Authenticator selection criteria. | | challenge | Hex | Optional challenge. A random 32-byte hex value is generated if omitted. | | excludeCredentialIds | string[] | Credential IDs to exclude (prevent re-registration). | | name | string | Display name for the credential (shorthand for user.name). | | rp | { id: string; name: string } | Relying party identifier and display name. | | timeout | number | Timeout in milliseconds. | | user | { name: string; displayName?: string; id?: BufferSource } | User account descriptor. Alternative to name. |

Return Value

{ challenge: Hex; options: CredentialCreationOptions }

Challenge to store and the WebAuthn options to send to the client.

Registration.verify

Verifies a registration credential from the client. Validates the attestation, rpIdHash, challenge, and origin, and extracts the P-256 public key.

Usage
import { Registration } from 'webauthx/server'

const result = Registration.verify(credential, {
  challenge,
  origin: 'https://example.com',
  rpId: 'example.com',
})
Parameters

| Parameter | Type | Description | | --- | --- | --- | | credential | Registration.Credential | The credential from the client. | | options.challenge | Hex \| Uint8Array \| ((challenge: string) => boolean) | Expected challenge value or async validator function. | | options.origin | string \| string[] | Expected origin(s) (e.g. "https://example.com"). | | options.rpId | string | Relying party ID (e.g. "example.com"). | | options.userVerification | string | User verification requirement. Default: 'required'. |

Return Value

Registration.Response

License

MIT