Passkey authentication for your web apps. Supports React, Angular, Vue, SvelteKit & others.
Project website »
View Demo
·
Documentation
·
Tutorial
Passlock.demo.mp4
Table of Contents
Really simple Passkey client library. You don't need to learn the underlying WebAuthn API or protocols, and all the backend stuff is handled for you. It's a simple 3 step process:
- Use the
@passlock/client
library to register or authenticate a passkey - This will generate a token, send it to your backend
- Use the
@passlock/node
library to verify the token and obtain the user & passkey details
Tip
Not using a Node backend? - No problem! you can make a REST call to the Passlock API to verify a secure token and obtain the user & passkey details.
Passkeys and the WebAuthn API are quite complex. We've taken an opinionated approach to simplify things for you. Following the 80/20 principle we've tried to focus on the features most valuable to developers and users. We welcome feature requests so do get in touch.
-
🔐 Primary & secondary authentication - Replace password based logins with passkeys, or use passkeys alongside passwords for secondary authentication.
-
☝🏻 Biometrics - We've made it really easy to implement facial or fingerprint recognition in your webapps.
-
🔐 Step up authentication - Require biometric or PIN verification for some operations, whilst allowing one-tap authentication for others.
-
🖥️ Full management console - Manage all security related aspects of your userbase through a web based console.
-
🕵️ Audit trail - View a full audit trail for each user: when they add a new passkey, when they login, verify their email address and much more.
Along with:
-
✉️ Mailbox verification - Passlock also handles mailbox verification emails (which are more complex than you might think)
-
🔑 Credential export - Decided to roll your own passkey code? No problem - you can export your users' credentials (including public keys) and drop them into your own database.
And more!
Viewing a user's authentication activity on their profile page
Create a free account on passlock.dev and obtain your clientId
(for the frontend), apiKey
(for the backend), and tenancyId
(frontend & backend).
This will depend on your package manager:
npm add @passlock/client
This quickstart guide illustrates the simplest scenario, using token based verification i.e. the client library returns a token which you send to your backend. Your backend then uses the @passlock/node library to verify the token.
An alternative flow uses JWTs with public keys to avoid the backend REST call. Please see the documentation for more details (coming soon).
Note: The flow is conceptually similar to OAuth2/OIDC but without the redirects.
You just need to call registerPasskey()
passing in a few details. This will do three things:
- Generate a passkey and store it on the user's device
- Register the passkey in your Passlock vault
- Generate a token representing the new credential
You then send this token to your backend. Your backend verifies it using either the @passlock/node package or via a simple REST call.
import { Passlock, PasslockError } from '@passlock/client'
// you can find these details in the settings area of the Passlock console
const tenancyId = '...'
const clientId = '...'
const passlock = new Passlock({ tenancyId, clientId })
// to register a new passkey, call registerPasskey(). We're using placeholders for
// the user data. You should grab this from an HTML form, React store, Redux etc.
const [email, givenName, familyName] = ["[email protected]", "John", "Doe"]
// Passlock doesn't throw but instead returns a union: result | error
const result = await passlock.registerPasskey({ email, givenName, familyName })
// ensure Passlock didn't return an error
if (!PasslockError.isError(result)) {
// send the token to your backend (json/fetch or hidden form field etc)
console.log('Token: %s', result.token)
}
Your backend just needs to exchange the token for a Principal
representing the successful passkey registration. Here is an example using the @passlock/node
sdk:
import { Passlock } from '@passlock/node'
// API Keys can be found in your passlock console
const passlock = new Passlock({ tenancyId, apiKey })
// token comes from your frontend
const principal = await passlock.fetchPrincipal({ token })
// get the user id
console.log(principal.user.id)
Link the user.id
with a user entity in your own database, similar to the way you might link a user's Facebook or Google id. This could be as simple as an additional (indexed) column on your user table.
You can also make an HTTP GET request to the https://api.passlock.dev/{tenancyId}/token/{token}
endpoint, using whatever library you wish e.g. Python requests:
# Substitute API_KEY, TENANCY_ID and TOKEN for the real values
curl -s -H "Authorization: Bearer $API_KEY" https://api.passlock.dev/$TENANCY_ID/token/$TOKEN
This will return a JSON object including a user
:
{
"token": "2arafoq-8coasjl-qx4jz3x",
"user": {
"id": "khXCYCxcGwJTLoaG6kVxB",
},
"expiresAt": "2024-01-25T12:06:07.000Z"
}
Similar to registration, call authenticatePasskey()
to obtain a token, which you then pass to your backend.
import { Passlock, PasslockError } from '@passlock/client'
const tenancyId = '...'
const clientId = '...'
const passlock = new Passlock({ tenancyId, clientId })
const result = await passlock.authenticatePasskey()
if (!PasslockError.isError(result)) {
// send the token to your backend for verification
console.log('Token: %s', result.token)
}
Exactly the same as for registration. Exchange the token for a Principal
and use the user.id
to lookup your own user entity.
This was a very quick overview. Please see the tutorial and documentation for more information.
Questions? Please use the GitHub discussions or see the contact details on our main project site.