@capgo/capacitor-passkey
v8.3.1
Published
Capacitor passkey plugin with a WebAuthn-style shim for Capacitor apps.
Maintainers
Readme
@capgo/capacitor-passkey
Passkeys for Capacitor with a browser-style WebAuthn shim.
Why this plugin
Most Capacitor apps already have browser-oriented passkey code based on:
await navigator.credentials.create({ publicKey: registrationOptions });
await navigator.credentials.get({ publicKey: requestOptions });This plugin keeps that shape in a Capacitor app:
- It can auto-patch
navigator.credentials.create/getforpublicKeyrequests. - It forwards the call to native passkey APIs on iOS and Android.
- It returns browser-like credential objects so existing code can keep working.
- It can auto-configure the generated iOS and Android host projects during
cap sync/update. - It also exposes direct JSON-safe methods when your backend already returns WebAuthn JSON.
What it does not do:
- It does not generate backend challenges for you.
- It does not remove the need for your website to host
apple-app-site-associationandassetlinks.json. - It does not make Android native passkeys report your website's HTTPS origin to the server. On Android, normal apps use the app origin (
android:apk-key-hash:...).
Documentation
The most complete doc is available here: https://capgo.app/docs/plugins/passkey/
Compatibility
| Plugin version | Capacitor compatibility | Maintained | | -------------- | ----------------------- | ---------- | | v8.*.* | v8.*.* | ✅ | | v7.*.* | v7.*.* | On demand | | v6.*.* | v6.*.* | ❌ | | v5.*.* | v5.*.* | ❌ |
Note: The major version of this plugin follows the major version of Capacitor. Use the version that matches your Capacitor installation.
Install
bun add @capgo/capacitor-passkeyBrowser-Like Setup
- Configure the plugin once in
capacitor.config.tsorcapacitor.config.json. - Import the plugin from the standard package entrypoint.
- Call
CapacitorPasskey.autoShimWebAuthn()once during app bootstrap. - Keep your existing browser
navigator.credentials.create/getcode unchanged.
1. Configure capacitor.config.*
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;Config keys:
origin: the primary HTTPS relying-party origin for the app.domains: optional extra relying-party hostnames to wire natively duringcap sync/update.autoShim: defaults totrue. This only controls the nativecap sync/updateauto-configuration hook.
Then sync native projects:
bunx cap syncDuring cap sync / cap update, the plugin automatically patches the generated host app:
- iOS: updates the entitlements file and wires
CODE_SIGN_ENTITLEMENTSif needed. - Android: injects
asset_statementsmetadata and writes a generated string resource.
You do not need to manually edit the host project files every time.
2. Install The Shim During Bootstrap
import { CapacitorPasskey } from '@capgo/capacitor-passkey';
await CapacitorPasskey.autoShimWebAuthn();That call reads plugins.CapacitorPasskey from the native Capacitor config and installs the WebAuthn shim explicitly.
3. Keep Existing WebAuthn Calls
After that bootstrap call, your browser-style code can stay the same:
const registration = await navigator.credentials.create({
publicKey: {
challenge: crypto.getRandomValues(new Uint8Array(32)),
rp: {
id: 'signin.example.com',
name: 'Example Inc',
},
user: {
id: crypto.getRandomValues(new Uint8Array(32)),
name: '[email protected]',
displayName: 'Ada Lovelace',
},
pubKeyCredParams: [
{ type: 'public-key', alg: -7 },
{ type: 'public-key', alg: -257 },
],
},
});
const authentication = await navigator.credentials.get({
publicKey: {
challenge: crypto.getRandomValues(new Uint8Array(32)),
rpId: 'signin.example.com',
},
});What The Hook Configures
The plugin hook only patches the native host app files that Capacitor generates.
- It does not touch your app source code.
- It does not require you to permanently hand-edit Xcode or Android project files.
- It does not publish or generate the website association files for you.
Direct JSON-safe API
If your backend already returns PublicKeyCredentialCreationOptionsJSON or PublicKeyCredentialRequestOptionsJSON, you can call the plugin directly:
import { CapacitorPasskey } from '@capgo/capacitor-passkey';
const registration = await CapacitorPasskey.createCredential({
origin: 'https://signin.example.com',
publicKey: registrationOptionsFromBackend,
});
const authentication = await CapacitorPasskey.getCredential({
origin: 'https://signin.example.com',
publicKey: requestOptionsFromBackend,
});Website Files You Still Need
Passkeys only work when your app is associated with the same relying-party domain as your website.
iOS Website Association File
Host an apple-app-site-association file on your relying-party domain:
https://signin.example.com/.well-known/apple-app-site-associationExample:
{
"webcredentials": {
"apps": [
"ABCDE12345.app.capgo.passkey.example"
]
}
}Notes:
- The file must be served with HTTP
200. - Do not add a
.jsonextension. - The
webcredentialsdomain must match the relying-party id you use for passkeys. - The plugin hook writes the associated domains entitlement for you during
cap sync/update. - On iOS 17.4 and newer, the plugin uses the browser-style client-data API so the configured HTTPS origin is reflected in
clientDataJSON.
Android Website Association File
Host a Digital Asset Links file at:
https://signin.example.com/.well-known/assetlinks.jsonExample:
[
{
"relation": [
"delegate_permission/common.handle_all_urls",
"delegate_permission/common.get_login_creds"
],
"target": {
"namespace": "android_app",
"package_name": "app.capgo.passkey.example",
"sha256_cert_fingerprints": [
"AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88:99"
]
}
}
]- Use the same domain as your relying-party id.
- Include every signing certificate fingerprint you need, including debug builds if you test them.
- The plugin hook writes the
asset_statementsmetadata and generated string resource for you duringcap sync/update. - Your website still needs to serve the actual
assetlinks.jsonfile.
Backend Notes
This plugin preserves the front-end WebAuthn API shape, but native platforms are not identical to a browser backend contract.
- iOS 17.4+ can encode the HTTPS origin you configure for the shim or direct API.
- Android Credential Manager does not act like a privileged browser app. The native response origin is tied to the Android app signature (
android:apk-key-hash:...), not automatically to your website. - With Digital Asset Links configured, Android can still use the same relying party and passkeys as your website. The part that differs is the literal
clientDataJSON.originstring. - If your server strictly validates
clientDataJSON.origin, allow the Android app origin alongside your web origin. - Your backend still needs the normal WebAuthn challenge lifecycle and signature verification.
Web Behavior
- On the web, the plugin forwards to the real browser WebAuthn API.
- On native Capacitor, the shim returns browser-like credential objects backed by native APIs.
- Call
CapacitorPasskey.autoShimWebAuthn()once during bootstrap before using browser-style WebAuthn calls. - Conditional mediation currently returns
false.
Example App
The example-app/ folder demonstrates the auto-shim flow:
example-app/capacitor.config.jsonconfigures the plugin.example-app/src/main.jsimportsCapacitorPasskeyfrom@capgo/capacitor-passkey.example-app/src/main.jscallsCapacitorPasskey.autoShimWebAuthn()during bootstrap.- The actual registration and authentication still go through
navigator.credentials.create/get.
API
shimWebAuthn(...)getConfiguration()autoShimWebAuthn(...)createCredential(...)getCredential(...)isSupported()getPluginVersion()- Interfaces
- Type Aliases
Capacitor Passkey plugin.
Use autoShimWebAuthn() to keep existing navigator.credentials.create/get
code working inside a Capacitor app.
shimWebAuthn(...)
shimWebAuthn(options?: ShimWebAuthnOptions | undefined) => voidInstall a browser-style WebAuthn shim on top of the native plugin.
The shim patches navigator.credentials.create/get for publicKey
requests and returns browser-like credential objects.
Use this when you want to override the auto-loaded config manually.
| Param | Type |
| ------------- | ------------------------------------------------------------------- |
| options | ShimWebAuthnOptions |
Since: 1.0.0
getConfiguration()
getConfiguration() => Promise<PasskeyRuntimeConfiguration>Load plugin configuration from the host Capacitor app.
This reads plugins.CapacitorPasskey from capacitor.config.*.
Returns: Promise<PasskeyRuntimeConfiguration>
Since: 1.1.0
autoShimWebAuthn(...)
autoShimWebAuthn(options?: ShimWebAuthnOptions | undefined) => Promise<PasskeyRuntimeConfiguration>Install the browser-style shim using host app configuration.
This is the easiest way to keep existing browser WebAuthn code working:
configure the plugin in capacitor.config.*, then call this once during
app bootstrap.
| Param | Type |
| ------------- | ------------------------------------------------------------------- |
| options | ShimWebAuthnOptions |
Returns: Promise<PasskeyRuntimeConfiguration>
Since: 1.1.0
createCredential(...)
createCredential(options: CreateCredentialOptions) => Promise<PasskeyRegistrationCredential>Register a passkey from a JSON-safe WebAuthn request.
This method is useful when your backend already returns the
PublicKeyCredentialCreationOptionsJSON form.
| Param | Type |
| ------------- | --------------------------------------------------------------------------- |
| options | CreateCredentialOptions |
Returns: Promise<PasskeyRegistrationCredential>
Since: 1.0.0
getCredential(...)
getCredential(options: GetCredentialOptions) => Promise<PasskeyAuthenticationCredential>Authenticate with an existing passkey from a JSON-safe WebAuthn request.
This method is useful when your backend already returns the
PublicKeyCredentialRequestOptionsJSON form.
| Param | Type |
| ------------- | --------------------------------------------------------------------- |
| options | GetCredentialOptions |
Returns: Promise<PasskeyAuthenticationCredential>
Since: 1.0.0
isSupported()
isSupported() => Promise<PasskeySupportResult>Report whether passkeys are available in the current runtime.
Returns: Promise<PasskeySupportResult>
Since: 1.0.0
getPluginVersion()
getPluginVersion() => Promise<PluginVersionResult>Returns the current platform implementation version marker.
Returns: Promise<PluginVersionResult>
Since: 1.0.0
Interfaces
ShimWebAuthnOptions
Options used when installing the browser-style shim.
| Prop | Type | Description |
| ------------ | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| origin | string | Optional HTTPS origin to encode into iOS 17.4+ clientDataJSON. Use this when your Capacitor app runs from capacitor://localhost but your relying party expects https://signin.example.com. |
| force | boolean | Force the shim even if the runtime already exposes navigator.credentials. Defaults to false. |
PasskeyRuntimeConfiguration
Runtime configuration loaded from the host app's Capacitor config.
This is the shape returned by getConfiguration().
| Prop | Type | Description |
| -------------- | ---------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| autoShim | boolean | Whether the native cap sync/update hook should wire host projects automatically. Defaults to true. |
| origin | string | Optional HTTPS origin used by the config-driven shim install. On iOS 17.4+ this origin is encoded into clientDataJSON. |
| domains | string[] | Domains associated with the app for passkey usage. These come from domains in Capacitor config plus the hostname derived from origin when available. |
| platform | 'ios' | 'android' | 'web' | Current runtime platform. |
PasskeyRegistrationCredential
JSON-safe registration credential returned by the plugin.
| Prop | Type | Description |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- |
| id | string | Base64url-encoded credential identifier. |
| rawId | string | Base64url-encoded raw credential identifier. |
| type | PasskeyCredentialType | Credential type. Always public-key. |
| authenticatorAttachment | PasskeyAuthenticatorAttachment | Optional authenticator attachment reported by the platform. |
| clientExtensionResults | Record<string, unknown> | Client extension results returned by the platform. |
| response | PasskeyAuthenticatorAttestationResponseJSON | Registration response payload. |
PasskeyAuthenticatorAttestationResponseJSON
JSON-safe attestation response payload.
All binary fields are base64url encoded.
| Prop | Type | Description |
| ------------------------ | --------------------- | -------------------------------------------------------------------- |
| clientDataJSON | string | Base64url-encoded clientDataJSON. |
| attestationObject | string | Base64url-encoded attestation object. |
| publicKey | string | Optional base64url-encoded public key when provided by the platform. |
| publicKeyAlgorithm | number | Optional public key algorithm when provided by the platform. |
| transports | string[] | Optional transport list when provided by the platform. |
CreateCredentialOptions
Direct registration request for the plugin transport.
| Prop | Type | Description |
| --------------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
| publicKey | PasskeyPublicKeyCredentialCreationOptionsJSON | JSON-safe registration request. |
| origin | string | Optional HTTPS origin to use for iOS 17.4+ browser-style clientDataJSON. |
PasskeyPublicKeyCredentialCreationOptionsJSON
JSON-safe registration request options.
All binary fields must be base64url encoded.
| Prop | Type | Description |
| ---------------------------- | --------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| challenge | string | Base64url-encoded challenge. |
| rp | PasskeyRelyingParty | Relying party information. |
| user | PasskeyUserEntity | User information. |
| pubKeyCredParams | PasskeyCredentialParameter[] | Supported credential algorithms. |
| timeout | number | Optional timeout hint in milliseconds. |
| excludeCredentials | PasskeyCredentialDescriptor[] | Optional credentials that must be excluded during registration. |
| authenticatorSelection | PasskeyAuthenticatorSelection | Optional authenticator preferences. |
| attestation | PasskeyAttestation | Optional attestation preference. |
| hints | string[] | Optional hints copied from the JSON form used by modern WebAuthn toolkits. |
| extensions | Record<string, unknown> | Optional extensions copied as-is into the request JSON. |
PasskeyRelyingParty
JSON-safe relying party information.
| Prop | Type | Description |
| ---------- | ------------------- | --------------------------------------------------------------------------------------------------- |
| id | string | Relying party identifier. If omitted, the shim derives it from the configured origin when possible. |
| name | string | Human-readable relying party name. |
PasskeyUserEntity
JSON-safe WebAuthn user entity.
Binary identifiers must be base64url encoded.
| Prop | Type | Description |
| ----------------- | ------------------- | ------------------------------------------------- |
| id | string | Base64url-encoded user handle. |
| name | string | User name shown by the authenticator. |
| displayName | string | Optional display name shown by the authenticator. |
PasskeyCredentialParameter
JSON-safe credential parameter entry.
| Prop | Type | Description |
| ---------- | ----------------------------------------------------------------------- | ------------------------------------------------ |
| type | PasskeyCredentialType | Credential type. Only public-key is supported. |
| alg | number | COSE algorithm identifier. |
PasskeyCredentialDescriptor
JSON-safe representation of a public key credential descriptor.
Binary identifiers must be base64url encoded.
| Prop | Type | Description |
| ---------------- | ----------------------------------------------------------------------- | ------------------------------------------------ |
| id | string | Base64url-encoded credential identifier. |
| type | PasskeyCredentialType | Credential type. Only public-key is supported. |
| transports | string[] | Optional transport hints copied from WebAuthn. |
PasskeyAuthenticatorSelection
JSON-safe authenticator selection options.
| Prop | Type | Description |
| ----------------------------- | ----------------------------------------------------------------------------------------- | --------------------------------------- |
| authenticatorAttachment | PasskeyAuthenticatorAttachment | Optional authenticator attachment hint. |
| residentKey | PasskeyResidentKey | Optional resident key preference. |
| requireResidentKey | boolean | Legacy resident key requirement flag. |
| userVerification | PasskeyUserVerification | Optional user verification preference. |
PasskeyAuthenticationCredential
JSON-safe authentication credential returned by the plugin.
| Prop | Type | Description |
| ----------------------------- | --------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- |
| id | string | Base64url-encoded credential identifier. |
| rawId | string | Base64url-encoded raw credential identifier. |
| type | PasskeyCredentialType | Credential type. Always public-key. |
| authenticatorAttachment | PasskeyAuthenticatorAttachment | Optional authenticator attachment reported by the platform. |
| clientExtensionResults | Record<string, unknown> | Client extension results returned by the platform. |
| response | PasskeyAuthenticatorAssertionResponseJSON | Assertion response payload. |
PasskeyAuthenticatorAssertionResponseJSON
JSON-safe assertion response payload.
All binary fields are base64url encoded.
| Prop | Type | Description |
| ----------------------- | --------------------------- | --------------------------------------- |
| clientDataJSON | string | Base64url-encoded clientDataJSON. |
| authenticatorData | string | Base64url-encoded authenticator data. |
| signature | string | Base64url-encoded signature. |
| userHandle | string | null | Optional base64url-encoded user handle. |
GetCredentialOptions
Direct authentication request for the plugin transport.
| Prop | Type | Description |
| --------------- | --------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
| publicKey | PasskeyPublicKeyCredentialRequestOptionsJSON | JSON-safe authentication request. |
| mediation | string | Optional mediation hint. conditional currently falls back to an explicit prompt. |
| origin | string | Optional HTTPS origin to use for iOS 17.4+ browser-style clientDataJSON. |
PasskeyPublicKeyCredentialRequestOptionsJSON
JSON-safe authentication request options.
All binary fields must be base64url encoded.
| Prop | Type | Description |
| ---------------------- | --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| challenge | string | Base64url-encoded challenge. |
| timeout | number | Optional timeout hint in milliseconds. |
| rpId | string | Optional relying party identifier. If omitted, the shim derives it from the configured origin when possible. |
| allowCredentials | PasskeyCredentialDescriptor[] | Optional allow list copied from WebAuthn. |
| userVerification | PasskeyUserVerification | Optional user verification preference. |
| hints | string[] | Optional hints copied from the JSON form used by modern WebAuthn toolkits. |
| extensions | Record<string, unknown> | Optional extensions copied as-is into the request JSON. |
PasskeySupportResult
Passkey support status for the current runtime.
| Prop | Type | Description |
| -------------------------- | ---------------------------------------- | ------------------------------------------------------ |
| available | boolean | Whether passkeys are available on the current runtime. |
| conditionalMediation | boolean | Whether conditional mediation is available. |
| platform | 'ios' | 'android' | 'web' | Current platform identifier. |
PluginVersionResult
Plugin version payload.
| Prop | Type | Description |
| ------------- | ------------------- | ------------------------------------------------------------------- |
| version | string | Version identifier reported by the current platform implementation. |
Type Aliases
PasskeyCredentialType
Supported WebAuthn credential type.
'public-key'
PasskeyAuthenticatorAttachment
Supported authenticator attachment values.
'platform' | 'cross-platform'
Record
Construct a type with a set of properties K of type T
{ [P in K]: T; }
PasskeyResidentKey
Supported resident key preferences.
'discouraged' | 'preferred' | 'required'
PasskeyUserVerification
Supported user verification preferences.
'discouraged' | 'preferred' | 'required'
PasskeyAttestation
Supported attestation preferences.
'none' | 'indirect' | 'direct' | 'enterprise'
