@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
✅ Supported Platforms
Client side:
- ✅ Chrome
- ✅ Edge
- ✅ Firefox
- ✅ Safari
- ✅ Opera
- ❌ (old) Internet Explorer 11
Basically, it supports all browsers that support WebAuthn API including the
getPublicKey()
andgetPublicKeyAlgorithm()
methods. Note that it might also depend on the password manager used, which will also be supported as long as it is specification compliant.
Server side:
- ✅ NodeJS 19+
- ✅ Cloudflare Workers
- ✅ All other JS platforms that support WebCrypto API
- ✅ All other server side libraries of other programming languages, as long as they use the default payload generated by the WebAuthn API.
Note: apparently, native iOS / macOS clients written in Switft are not compatible with the server-side part of this library, as they do not provide the
publicKey
andpublicKeyAlgorithm
properties during registration in the first place. See #95.