By calling loginWithPasskey(), the SDK stores the session and active client in localStorage. The signing key material remains securely stored in the browser’s IndexedDB and is never extractable. Turnkey uses this public key to scope and encrypt the session to the appropriate user.

Steps using @turnkey/sdk-react

This process is made seamless by leveraging our React package. Read on for a non-React implementation below.

1

Initialize the React Provider

import { TurnkeyProvider } from "@turnkey/sdk-react";

const turnkeyConfig = {
  apiBaseUrl: "https://api.turnkey.com",
  defaultOrganizationId: process.env.TURNKEY_ORGANIZATION_ID,
  rpId: process.env.RPID,
};

...

<div className="App">
  <TurnkeyProvider config={turnkeyConfig}>
    {/* Your app components */}
  </TurnkeyProvider>
</div>
2

Login with a Passkey and Create a Session

import { useTurnkey } from "@turnkey/sdk-react";

const { passkeyClient, indexedDbClient } = useTurnkey();

await indexedDbClient.init();
const publicKey = await indexedDbClient.getPublicKey();

await passkeyClient.loginWithPasskey({
  publicKey,
  sessionType: "READ_WRITE", // or "READ_ONLY"
  expirationSeconds: 900,
});
3

Use the session to make requests

const { getActiveClient } = useTurnkey();
const client = await getActiveClient();

const whoami = await client.getWhoami({
  organizationId: <your-org-id>,
});

getActiveClient() returns the currently active client (e.g. IndexedDb-backed), refreshing automatically if needed.

Alternative Steps (non-React)

1

Initialize the Passkey and IndexedDB Clients

import { Turnkey } from "@turnkey/sdk-browser";

const turnkey = new Turnkey({
  apiBaseUrl: "https://api.turnkey.com",
  defaultOrganizationId: process.env.TURNKEY_ORGANIZATION_ID,
});

const passkeyClient = turnkey.passkeyClient();
const indexedDbClient = turnkey.indexedDbClient();

await indexedDbClient.init();
2

Login with a Passkey and Create a Session

const publicKey = await indexedDbClient.getPublicKey();

await passkeyClient.loginWithPasskey({
  publicKey,
  sessionType: "SESSION_TYPE_READ_WRITE", // or "SESSION_TYPE_READ_ONLY"
  expirationSeconds: 900,
});
3

Use the session to make requests

const whoami = await turnkey.getWhoami({
  organizationId: <your-org-id>,
});

Once loginWithPasskey completes, the session is stored in localStorage and all requests are signed using the IndexedDb-backed keypair.