Skip to content

Authenticate a passkey

The process is almost identical to passkey registration. You’ll use the Passlock browser library to trigger passkey login on the device, then send the resulting code to your backend.

sequenceDiagram
  participant Frontend
  participant Browser as @passlock/browser
  participant Backend
  participant Server as @passlock/server

  Frontend->>Browser: authenticatePasskey()
  Browser-->>Frontend: id_token, code

  Frontend->>Backend: code

  Backend->>Server: exchangeCode(code)
  Server-->>Backend: authenticatorId

  Backend->>Backend: lookupUser(authenticatorId)

This time you don’t need a username. Passkeys are discoverable, meaning the browser/device will prompt the user to select the passkey they want to sign in with:

import { Passlock } from "@passlock/browser";
// get this from your development tenancy settings
const tenancyId = "myTenancyId";
const passlock = new Passlock({ tenancyId });
// call this in a button click handler or similar action
const result = await passlock.authenticatePasskey({});
if (result.success) {
// send this to your backend
console.log({ code: result.value.code });
} else {
console.error(result.error.message);
}
Choose your code style

As before, submit the code to your backend.

The process is exactly the same as for the registration flow.

The ExtendedPrincipal includes an authenticatorId, which you previously linked to a user account in your backend system. You’ll use this ID to lookup the associated user and log them in.

import { Passlock } from "@passlock/server";
// get these from your development tenancy settings
const tenancyId = "myTenancyId";
const apiKey = "myApiKey";
const passlock = new Passlock({ tenancyId, apiKey });
const result = await passlock.exchangeCode({ code });
if (result.success) {
// implement this
lookupUser(result.value.authenticatorId);
} else {
console.error(result.error.message);
}
Choose your code style

If you’re unable to use the @passlock/server library, you can make a simple REST call:

GET /{tenancyId}/principal/{code} HTTP/1.1
Host: https://api.passlock.dev
Accept: application/json
Authorization: Bearer {apiKey}