
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
webauthn-authenticator
Advanced tools
A standalone TypeScript library for mocking WebAuthn in browsers, particularly useful for Playwright testing and headless browser automation
A standalone TypeScript library for mocking WebAuthn in browsers, particularly useful for Playwright testing and headless browser automation.
navigator.credentials.create and navigator.credentials.get with in-memory implementationsThe library has been refactored into a modular architecture:
navigator.credentials APInpm install
# 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
The project includes a demo application that showcases the WebAuthn authenticator in action. Visit the development server to see:
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')
})
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
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!
})
createPublicKeyCredential(options) - Creates a new WebAuthn credentialgetPublicKeyCredential(options) - Retrieves an existing credentialcancelNextOperation() - Cancels the next create/get operation (throws NotAllowedError)credentials - Object containing all created credentials keyed by credential IDinstallWebAuthnMock(options) - Installs the WebAuthn mock in browserdeserializePublicKeyCredentialAttestion(credential) - Converts serialized attestation to browser formatdeserializePublicKeyCredentialAssertion(credential) - Converts serialized assertion to browser formatThis 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.
crypto module for key generation and signingThe project includes comprehensive tests:
# Build library for distribution
npm run build:lib
# Build demo application
npm run build
This project is derived from the SendApp monorepo and maintains compatibility with its WebAuthn implementation.
This is a workspace for developing a standalone version of the SendApp WebAuthn authenticator. When contributing:
The library requires modern browsers with support for:
FAQs
A standalone TypeScript library for mocking WebAuthn in browsers, particularly useful for Playwright testing and headless browser automation
We found that webauthn-authenticator demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.