Skip to main content

Create a User Passkey Session

A passkey session is an expiring session enabled by an initial passkey authentication. You could think of this as a "lightning mode" of sorts: creating a passkey session allows users to authenticate subsequent requests touch-free. Under the hood, this is powered by our iframeStamper. These sessions are enabled by creating a short-lived embedded API key in the browser, and encrypting it to our auth iframe. This is largely similar to our Email Auth setup.

By calling createPasskeySession(), the SDK stores the resulting auth bundle in local storage for later retrieval, and also returns it to the caller. If you don't want to rely on getActiveClient() and instead want to manage the stampers yourself, you can inject the auth bundle into the iframe — see the code for specifics.

Steps using @turnkey/sdk-react

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

1. Initialize the React Provider

import { TurnkeyProvider } from "@turnkey/sdk-react";
const turnkeyConfig = {
apiBaseUrl: "https://api.turnkey.com",
defaultOrganizationId: process.env.TURNKEY_ORGANIZATION_ID, // prefix with NEXT_PUBLIC for NextJS
rpId: process.env.RPID, // your application's domain
iframeUrl: "https://auth.turnkey.com"
}

...

<div className="App">
<TurnkeyProvider config={turnkeyConfig}>
// Rest of app ...
</TurnkeyProvider>
</div>

2. Call the createPasskeySession function

import { useTurnkey } from "@turnkey/sdk-react";
const { turnkey, authIframeClient } = useTurnkey();
const currentUser = await turnkey?.getCurrentUser(); // this assumes the user has already logged in via passkeyClient?.login()`}
const authBundle = await passkeyClient?.createPasskeySession(
currentUser?.userId!,
authIframeClient?.iframePublicKey!,
"900", // seconds. 900 == 15 minutes, but can be configured to any value
);

3. Use the passkey session for read and write requests

const { getActiveClient } = useTurnkey();
const currentClient = await getActiveClient();
// make arbitrary requests
const whoami = await currentClient.getWhoami({ organizationId: <your org ID> })

Note: getActiveClient() is a helper method designed to abstract away the need to check if a passkey session is still valid. If it has expired, this will default to the passkeyClient, in which case users will sign each request using their passkey.

Alternative Steps (non-React)

1. Initialize the Passkey Client

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();

2. Call the createPasskeySession function

const currentUser = await turnkey.getCurrentUser(); // this assumes the user has already logged in via passkeyClient.login()`}
const authIframeClient = await turnkey.iframeClient({
iframeContainer: document.getElementById("<iframe container id>"),
iframeUrl: "https://auth.turnkey.com",
});
const authBundle = await passkeyClient.createPasskeySession(
currentUser?.userId!,
authIframeClient?.iframePublicKey!,
"900", // seconds. 900 == 15 minutes, but can be configured to any value
);

3. Use the passkey session for read and write requests

if (authBundle) { // authBundle was generated in Step 2
const injected = await authIframeClient.injectCredentialBundle(
authBundle
);
if (injected) {
const whoamiResponse = await authIframeClient.getWhoami({
organizationId:
currentUser?.organization.organizationId ??
turnkey?.config.defaultOrganizationId!,
});
// if whoamiResponse is valid, you now have a working passkey session in the authIframeClient
await authIframeClient... // perform arbitrary requests
}
}