@passwordless-id/webauthn
This library greatly simplifies the usage of passkeys by invoking the WebAuthn protocol more conveniently. It is open source, opinionated, dependency-free and minimalistic.
This library is provided by Passwordless.ID, a free public identity provider.
👀 Demos
These demos are plain HTML/JS, not minimized. Just open the sources in your browser if you are curious.
📦 Installation
Modules (recommended)
npm install @passwordless-id/webauthn
The base package contains both client and server side modules. You can import the client
submodule or the server
depending on your needs.
import {client} from '@passwordless-id/webauthn'
import {server} from '@passwordless-id/webauthn'
Note: the brackets in the import are important!
Alternatives
For browsers, it can be imported using a CDN link in the page, or even inside the script itself.
<script type="module">
import {client} from src="https://cdn.jsdelivr.net/npm/@passwordless-id/[email protected]/dist/webauthn.min.js"
</script>
Lastly, a CommonJS variant is also available for old Node stacks, to be imported using require('@passwordless-id/webauthn')
. It's usage is discouraged though, in favor of the default ES modules.
Note that at least NodeJS 19+ is necessary. (The reason is that previous Node versions had no WebCrypto
being globally available, making it impossible to have a "universal build")
🚀 Getting started
There are multiple ways to use and invoke the WebAuthn protocol. What follows is just an example of the most straightforward use case.
Registration
import {client} from '@passwordless-id/webauthn'
await client.register({
challenge: 'a random string generated by the server',
user: 'John Doe'
})
By default, this registers a passkey on any authenticator (local or roaming) with preferred
user verification. For further options, see → Registration docs
Authentication
import {client} from '@passwordless-id/webauthn'
await client.authenticate({
challenge: 'a random string generated by the server'
})
By default, this triggers the native passkey selection dialog, for any authenticator (local or roaming) and with preferred
user verification. For further options, see → Authentication docs
Verification
import {server} from '@passwordless-id/webauthn'
await server.verifyRegistration(registration, expected)
await server.verifyAuthentication(authentication, expected)
Look at the docs for registration and authentication for the corresponding verification examples. Or simply interact with real-life examples in the Testing Playground.
📃 Changelog
The version 2 introduced breaking changes, different default behavior and different intermediate format. Basically, it's a complete overhaul and to understand "why" this version 2 was made, I recommend reading this blog post. In a very summarized way, it is to enhance support for security keys by default, reflect latest changes in the underlying specs and improve cross-compatibility with other server side libraries.
Some core changes are:
- Use platform authenticator by default => authenticator selection pops up by default
authenticatorType
was removed => usehints
instead- User verification default:
required
=>preferred
- Timeout: 1 minute => no timeout
- Response format changed
- Transports as part of
allowCredentials
The docs for the legacy version 1.x are found here