Skip to content

Authenticate a passkey

Similar to passkey registration, authentication is a three-step process:

  1. Authorised in your backend
  2. Authenticated in your frontend
  3. Verified in your backend

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

backend/authenticate.ts
import { Passlock } from "@passlock/server";
// from your development tenancy settings
const passlock = new Passlock({
tenancyId: "myTenancyId",
apiKey: "myApiKey"
});
const result = await passlock.authorizePasskeyAuthentication({
rpId: "example.com", // "localhost" for development
discoverable: true, // allow the user to select their passkey
});
if (result.success) {
return result.authenticationToken;
}

Pass the authenticationToken to authenticatePasskey:

frontend/authenticate.ts
import { Passlock } from "@passlock/browser";
const passlock = new Passlock({ tenancyId: "myTenancyId" });
loginButton.addEventListener("click", async () => {
const authenticationToken = await fetchTokenFromBackend();
const result = await passlock.authenticatePasskey({
authenticationToken
});
if (result.success) {
await submitTokenToBackend(result.value.code);
}
});

Submit the code to your backend.

After your backend exchanges the code with the Passlock API, use the userId or authenticatorId (passkeyId) to lookup the user and sign them in.

backend/authenticate.ts
import { Passlock } from "@passlock/server";
// from your development tenancy settings
const passlock = new Passlock({
tenancyId: "myTenancyId",
apiKey: "myApiKey"
});
const result = await passlock.exchangeCode({ code });
if (result.success) {
const user = await lookupUserById(result.value.userId);
// alternatively identify the user by their passkey id
const user = await lookupUserByPasskeyId(principal.authenticatorId);
};

The response is an ExtendedPrincipal.