Integrating Passkeys into your application
To securely handle passkey authentication in your application, embed the hosted Passkey UI in an iframe (web) or open it in a browser session (mobile). Below are best practices and code examples for both environments.
For more details, see the Create or Authenticate Passkey endpoint documentation.
Web Integration (React/Next.js)
Initiate Passkey Session
Request a passkey session from your backend, specifying the action (create
or auth
), and receive a hosted UI URL.
appName determines how the passkey will be named when it is created on your user’s device. Use your application’s name or a clear identifier so users can easily recognize it.
const requestPasskeySession = async (action: "create" | "auth") => {
const appName = "YourAppName";
// Generate a session key
const keypair = Keypair.generate();
const sessionKey = {
key: keypair.publicKey.toBase58(),
expiration: 900, // 15 minutes
};
const redirectUrl = encodeURIComponent(window.location.origin + "/");
const passkeyData = {
action: action,
sessionKey,
env: "devnet", // or 'mainnet'
metaInfo: {
appName: appName,
redirectUrl: redirectUrl,
},
};
// Get the passkey URL from your API
const response = await fetch(
`https://developer-api.squads.so/api/v1/passkeys`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Network": "devnet", // or 'mainnet'
"Authorization": "Bearer YOUR_API_KEY",
},
body: JSON.stringify({
action: action,
sessionKey,
metaInfo: {
appName: appName,
redirectUrl: redirectUrl,
},
}),
}
);
const data = await response.json();
setPasskeyUrl(data.url);
setShowIframe(true);
};
Embed Hosted UI
Add the hosted Passkey UI to your app using an iframe
with the correct WebAuthn permissions.
<iframe
allow="publickey-credentials-get *; publickey-credentials-create *"
src={passkeyUrl}
style={{ display: "none" }}
onError={(e) => {
console.error("Iframe error:", e);
}}
onLoad={() => {
console.log("Iframe loaded successfully");
}}
/>
Handle Authentication Result
Listen for messages from the iframe to receive the session token or handle errors, then use the session token as a signer in Smart Account operations.
On successful authentication, the iframe will post a message of type authz_complete
containing a sessionToken
and the onchain passkey address. On error, a message of type authz_error
will be sent with an error description. You can also extract these values from the redirect URL if using a full-page redirect.
useEffect(() => {
const handleMessage = (event: MessageEvent) => {
if (event.data.type === "authz_complete") {
// event.data.sessionToken: Use this as a signer for Smart Account operations
// event.data.passkeyAddress: The onchain address of the created or authenticated passkey
console.log("Authorization complete:", event.data);
const sessionToken = event.data.sessionToken;
const passkeyAddress = event.data.passkeyAddress;
// Handle successful authentication
} else if (event.data.type === "authz_error") {
// event.data.error: Error description
console.log("Authorization error:", event.data.error);
// Handle authentication error
}
};
window.addEventListener("message", handleMessage);
return () => window.removeEventListener("message", handleMessage);
}, []);
React Native Integration
Initiate Passkey Session
Request a passkey session from your backend and receive the hosted UI URL.
import { Linking } from 'react-native';
const appName = "YourAppName";
const action = "create"; // or "auth"
const apiKey = "YOUR_API_KEY";
const network = "devnet"; // or 'mainnet'
const redirectUri = Linking.createURL("login");
// Generate a session key
const keypair = Keypair.generate();
const sessionKey = {
key: keypair.publicKey.toBase58(),
expiration: 900, // 15 minutes
};
const passkeyData = {
action,
sessionKey,
metaInfo: {
appName,
redirectUrl: redirectUri,
},
};
// Get the passkey URL
const response = await fetch("https://developer-api.squads.so/api/v1/passkeys", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${apiKey}`,
"x-squads-network": network,
},
body: JSON.stringify(passkeyData),
});
const data = await response.json();
Open Hosted UI in Browser
Launch the Passkey UI in the device browser using WebBrowser.openAuthSessionAsync
.
const result = await WebBrowser.openAuthSessionAsync(data.url, redirectUri);
Process Redirect Result
Handle the redirect and extract the session token from the result for use as a signer in Smart Account operations.
// result is encoded in url
const parsed = LinkingExpo.parse(result.url);
const status = parsed.queryParams?.status;
if (status === "success") {
// parseUrl for externally signed account
} else {
// handle error
}
For more details, see the Create or Authenticate Passkey endpoint documentation.