Skip to main content

Register a passkey

The Passlock client library handles passkey creation and device registration. It also registers the passkey in your Passlock vault. You just need to link the Passlock user with a user entity in your own backend.

Prerequisites

You'll need to create a Passlock account (it's free). Once you've created your account, head to the settings section to obtain your:

  • Tenancy ID
  • Client ID
  • API Key

Install the client library

Add the Passlock client to your frontend:

npm install @passlock/client --save

Capture registration data

At a minimum you'll need the user's email, but we recommend also capturing the givenName and lastName.

Why do we need the email?
  1. Passkeys are tied to a specific hostname. If you ever change your domain everything will break 💥 Similar to a reset password flow, storing the email allows you to authenticate a user and regenerate a passkey for the new domain.

  2. The browser needs to associate the passkey with a username. An email clearly identifies the specific account and is likely to be common across all authentication methods. If we don't use the email, a user could potentially use jdoe for your legacy username/password page, but johnd for their passkey account 🤮

Create a Passlock instance

You can instantiate a Passlock or PasslockUnsafe instance, the difference being that PasslockUnsafe rejects, whereas Passlock returns a union type: Promise<Result | PasslockError>. We'll use the "safe" Passlock class for this tutorial.

import { Passlock, PasslockError } from '@passlock/client'

// get tenancyId and clientId from your passlock console
// settings (https://console.passlock.dev/settings)
const passlock = new Passlock({ tenancyId, clientId })

Register the passkey

The Passlock client library handles the creation and registration of the passkey. If the registration is successfull it returns a UserPrincipal including a token. You should forward this token to your backend as part of your registration flow.

register.ts
const result = await passlock.registerPasskey({ 
// capture this data from your user
email: 'jdoe@gmail.com',
givenName: 'John',
familyName: 'Doe',
// we'll explain this later
userVerification: 'discouraged'
})

// Passlock doesn't throw (by default), instead it returns
// PasslockError | Principal. Use PasslockError's static
// isError type guard to check for errors.
if (PasslockError.isError(result)) {
console.error(result)
} else {
// submit the token to your backend along with any other
// data captured on your registration form.
console.log("Token: %s", result.token)
}
User verification

You can ask the browser/device to perform local authentication before signing with the passkey. For now you'll disable this feature but we'll cover it later in the tutorial. You can read more about user verification.

Backend processing

Your backend just needs to call a REST endpoint to exchange the token for a UserPrincipal. Make a GET request to https://api.passlock.dev/{tenancyId}/token/{token}, replacing tenancyId and token with the appropriate values. You will also need to provide your API Key as an authorization header:

GET https://api.passlock.dev/{tenancyId}/token/{token}
Host: https://api.passlock.dev
Accept: application/json
Authorization: Bearer <API Key>

For now you'll just use curl to exchange the generated token for the principal. Replace the $API_KEY, $TENANCY and $TOKEN placeholders.

curl -s -H "Authorization: Bearer $API_KEY" "https://api.passlock.dev/$TENANCY/token/$TOKEN" | jq
output
{
"token": "2arafoq-8coasjl-qx4jz3x",
"sub": "khXCYCxcGwJTLoaG6kVxB",
"email": "jdoe@gmail.com",
"givenName": "John",
"familyName": "Doe",
"emailVerified": false,
"authType": "passkey",
"userVerified": false,
}
tip

jq is a really neat json formatter for the unix/mac command line.

Assuming you receive a 200 response, you can create (or update) a user in your database, linking their Passlock sub (subject/user id) to their local account. During subsequent authentication, you will receive the same Passlock sub, which you'll use to lookup your user's record.

warning

Don't use the Passlock sub as your database primary key. Generate your own PK, but store (and index) the Passlock sub

Next steps

If you tested the code yourself you've hopefully registered a passkey on your own device, with the username jdoe@gmail.com (or whatever email you hard coded). If you check the Passlock console you should see the new user. Now it's time to learn how to authenticate a user using their passkey...