@capgo/capacitor-passkey lets a Capacitor app keep the same WebAuthn flow you already use on the web:
await navigator.credentials.create({ publicKey: registrationOptions });
await navigator.credentials.get({ publicKey: requestOptions });
The plugin installs a shim for navigator.credentials.create() and navigator.credentials.get() on native platforms, forwards the request to iOS and Android passkey APIs, and returns browser-like credential objects back to your app.
bun add @capgo/capacitor-passkey
bunx cap sync
Add the plugin config in capacitor.config.ts or capacitor.config.json:
import type { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
appId: 'app.capgo.passkey.example',
appName: 'My App',
webDir: 'dist',
plugins: {
CapacitorPasskey: {
origin: 'https://signin.example.com',
autoShim: true,
domains: ['signin.example.com'],
},
},
};
export default config;
Run sync again after changing the config:
bunx cap sync
During sync, the plugin patches the generated native host projects:
asset_statements metadata for Digital Asset LinksImport the auto entrypoint in your app bootstrap:
import '@capgo/capacitor-passkey/auto';
After that, your existing browser-style passkey code can stay the same.
const credential = await navigator.credentials.create({
publicKey: registrationOptions,
});
const assertion = await navigator.credentials.get({
publicKey: requestOptions,
});
The plugin reduces app-side work, but passkeys still depend on the website trust files for your relying-party domain:
/.well-known/apple-app-site-association/.well-known/assetlinks.jsonThe full platform setup is documented here:
Android Credential Manager can share the same relying party and passkeys as your website when Digital Asset Links are configured, but the native assertion origin is not identical to a browser origin. If your backend strictly validates clientDataJSON.origin, make sure it accepts the Android app origin alongside your website origin.