-
-
Notifications
You must be signed in to change notification settings - Fork 24
feat: add passkey plugin docs #564
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
59 changes: 59 additions & 0 deletions
59
apps/docs/src/content/docs/docs/plugins/passkey/android.mdx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| --- | ||
| title: Android Setup | ||
| description: Configure passkeys on Android for @capgo/capacitor-passkey with Digital Asset Links and assetlinks.json. | ||
| sidebar: | ||
| order: 4 | ||
| --- | ||
|
|
||
| On Android, passkeys work with your website when the app and the relying-party domain are connected through Digital Asset Links. | ||
|
|
||
| ## What the plugin handles | ||
|
|
||
| After you add the plugin config and run `bunx cap sync`, the plugin patches the generated Android host project: | ||
|
|
||
| - injects the `asset_statements` manifest metadata | ||
| - writes the generated string resource referenced by that metadata | ||
|
|
||
| ## What you still need to host | ||
|
|
||
| You must publish `assetlinks.json` on the relying-party domain: | ||
|
|
||
| ```text | ||
| https://signin.example.com/.well-known/assetlinks.json | ||
| ``` | ||
|
|
||
| Example: | ||
|
|
||
| ```json | ||
| [ | ||
| { | ||
| "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" | ||
| ] | ||
| } | ||
| } | ||
| ] | ||
| ``` | ||
|
|
||
| ## Checklist | ||
|
|
||
| 1. Set `origin` and `domains` in `plugins.CapacitorPasskey` in `capacitor.config.*`. | ||
| 2. Run `bunx cap sync`. | ||
| 3. Use your real Android package name in `assetlinks.json`. | ||
| 4. Add every signing certificate fingerprint you need, including debug or internal signing keys if you test those builds. | ||
| 5. Host the file on the same domain you use as the relying-party ID. | ||
|
|
||
| ## Important behavior difference from a browser | ||
|
|
||
| With Digital Asset Links configured, Android can use the same relying party and passkeys as your website. The remaining difference is the literal origin reported in native `clientDataJSON`. | ||
|
|
||
| - A normal Android app does not behave like a privileged browser. | ||
| - The assertion origin can be tied to the Android app signature instead of your website origin. | ||
| - If your backend strictly validates `clientDataJSON.origin`, accept the Android app origin alongside the website origin. |
57 changes: 57 additions & 0 deletions
57
apps/docs/src/content/docs/docs/plugins/passkey/backend.mdx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| --- | ||
| title: Backend Notes | ||
| description: Understand the backend contract for @capgo/capacitor-passkey, including WebAuthn challenge handling and Android origin validation. | ||
| sidebar: | ||
| order: 5 | ||
| --- | ||
|
|
||
| Your backend still owns the normal WebAuthn ceremony: | ||
|
|
||
| - generate registration and authentication challenges | ||
| - verify attestation and assertion responses | ||
| - enforce relying-party ID and challenge validation | ||
| - store credentials and counters the same way you would for a browser flow | ||
|
|
||
| ## What stays the same | ||
|
|
||
| The plugin is designed to preserve the front-end shape of your existing WebAuthn code. | ||
|
|
||
| - On the web, it forwards to the real browser WebAuthn API. | ||
| - On native Capacitor, it returns browser-like credential objects backed by native passkey APIs. | ||
| - Your backend can keep the same challenge and verification pipeline. | ||
|
|
||
| ## What changes on Android | ||
|
|
||
| Android native passkeys are not identical to a browser trust model. | ||
|
|
||
| - Digital Asset Links let Android share the same relying party and credential ecosystem as your website. | ||
| - The literal `clientDataJSON.origin` value can still differ from the website origin. | ||
| - If your server rejects anything except `https://your-domain`, Android native assertions can fail even when the passkey is otherwise valid. | ||
|
|
||
| ## Recommended backend rule | ||
|
|
||
| Allow the expected browser origin and the expected Android app origin for the same relying party when you support native Android passkeys. | ||
|
|
||
| That gives you: | ||
|
|
||
| - browser support for the website | ||
| - native passkey support in the Capacitor app | ||
| - one passkey ecosystem for the same relying-party domain | ||
|
|
||
| ## If you need direct JSON-safe calls | ||
|
|
||
| If your backend already returns `PublicKeyCredentialCreationOptionsJSON` and `PublicKeyCredentialRequestOptionsJSON`, you can also use the direct plugin API instead of the browser-style shim: | ||
|
|
||
| ```ts | ||
| 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, | ||
| }); | ||
| ``` |
96 changes: 96 additions & 0 deletions
96
apps/docs/src/content/docs/docs/plugins/passkey/getting-started.mdx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| --- | ||
| title: Getting Started | ||
| description: Install @capgo/capacitor-passkey, configure the plugin once, and keep your browser-style WebAuthn code in a Capacitor app. | ||
| sidebar: | ||
| order: 2 | ||
| --- | ||
|
|
||
| import { Steps, Card, CardGrid } from '@astrojs/starlight/components'; | ||
| import { PackageManagers } from 'starlight-package-managers' | ||
|
|
||
| <Steps> | ||
| 1. **Install the package** | ||
| <PackageManagers pkg="@capgo/capacitor-passkey" pkgManagers={['bun']} /> | ||
|
|
||
| 2. **Sync native projects** | ||
| <PackageManagers type="exec" pkg="cap" args="sync" pkgManagers={['bun']} /> | ||
|
|
||
| 3. **Add the plugin config** | ||
|
|
||
| ```ts | ||
| 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; | ||
| ``` | ||
|
|
||
| 4. **Import the shim once** | ||
|
|
||
| ```ts | ||
| import '@capgo/capacitor-passkey/auto'; | ||
| ``` | ||
|
|
||
| 5. **Keep your normal WebAuthn flow** | ||
|
|
||
| ```ts | ||
| const registration = await navigator.credentials.create({ | ||
| publicKey: registrationOptions, | ||
| }); | ||
|
|
||
| const authentication = await navigator.credentials.get({ | ||
| publicKey: requestOptions, | ||
| }); | ||
| ``` | ||
| </Steps> | ||
|
|
||
| ## What the plugin config does | ||
|
|
||
| The config is read from `plugins.CapacitorPasskey` in `capacitor.config.*`. | ||
|
|
||
| - `origin`: primary HTTPS relying-party origin used by the shim and direct API | ||
| - `domains`: extra relying-party hostnames to patch into native config during sync | ||
| - `autoShim`: defaults to `true` when you use `@capgo/capacitor-passkey/auto` | ||
|
|
||
| ## What sync patches for you | ||
|
|
||
| When you run `bunx cap sync`, the plugin updates the generated native host project: | ||
|
|
||
| - iOS: associated domains entitlements and Xcode entitlements wiring when needed | ||
| - Android: `asset_statements` metadata and the generated resource used by the manifest | ||
|
|
||
| The hook does not publish your website trust files for you. You still need to host: | ||
|
|
||
| - `https://your-domain/.well-known/apple-app-site-association` | ||
| - `https://your-domain/.well-known/assetlinks.json` | ||
|
|
||
| ## Platform guides | ||
|
|
||
| <CardGrid> | ||
| <a href="/docs/plugins/passkey/ios/"> | ||
| <Card title="iOS setup" icon="open-book"> | ||
| Associated Domains and `apple-app-site-association`. | ||
| </Card> | ||
| </a> | ||
| <a href="/docs/plugins/passkey/android/"> | ||
| <Card title="Android setup" icon="open-book"> | ||
| Digital Asset Links and `assetlinks.json`. | ||
| </Card> | ||
| </a> | ||
| <a href="/docs/plugins/passkey/backend/"> | ||
| <Card title="Backend notes" icon="open-book"> | ||
| Origin validation and Android caveats. | ||
| </Card> | ||
| </a> | ||
| </CardGrid> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| --- | ||
| title: "@capgo/capacitor-passkey" | ||
| description: Passkeys for Capacitor with a browser-style WebAuthn shim, minimal JavaScript changes, and native setup generated during sync. | ||
| tableOfContents: false | ||
| next: false | ||
| prev: false | ||
| sidebar: | ||
| order: 1 | ||
| label: "Introduction" | ||
| hero: | ||
| tagline: Keep your browser-style WebAuthn code in a Capacitor app while the plugin handles native passkey calls and native host patching. | ||
| actions: | ||
| - text: Get started | ||
| link: /docs/plugins/passkey/getting-started/ | ||
| icon: right-arrow | ||
| variant: primary | ||
| - text: GitHub | ||
| link: https://github.com/Cap-go/capacitor-passkey/ | ||
| icon: external | ||
| variant: minimal | ||
| --- | ||
|
|
||
| import { Card, CardGrid } from '@astrojs/starlight/components'; | ||
|
|
||
| <CardGrid stagger> | ||
| <Card title="Browser-style API" icon="rocket"> | ||
| Keep `navigator.credentials.create()` and `navigator.credentials.get()` in your app instead of rewriting your passkey flow around a custom API. | ||
| </Card> | ||
| <Card title="Minimal app changes" icon="pencil"> | ||
| Add plugin config once, import `@capgo/capacitor-passkey/auto`, and keep the rest of your WebAuthn code close to the browser implementation. | ||
| </Card> | ||
| <Card title="Build-time native wiring" icon="setting"> | ||
| The plugin patches the generated iOS and Android host projects during sync so you do not need to keep hand-editing those files. | ||
| </Card> | ||
| <Card title="Platform notes included" icon="open-book"> | ||
| Follow the [Getting Started](/docs/plugins/passkey/getting-started/), [iOS setup](/docs/plugins/passkey/ios/), [Android setup](/docs/plugins/passkey/android/), and [backend notes](/docs/plugins/passkey/backend/). | ||
| </Card> | ||
| </CardGrid> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| --- | ||
| title: iOS Setup | ||
| description: Configure passkeys on iOS for @capgo/capacitor-passkey with Associated Domains and the apple-app-site-association file. | ||
| sidebar: | ||
| order: 3 | ||
| --- | ||
|
|
||
| On iOS, passkeys only work when the app is associated with the same relying-party domain as the website. | ||
|
|
||
| ## What the plugin handles | ||
|
|
||
| After you add the plugin config and run `bunx cap sync`, the plugin patches the generated iOS host project so you do not need to keep editing it manually: | ||
|
|
||
| - adds the `webcredentials:` associated domains entries for the configured domains | ||
| - wires `CODE_SIGN_ENTITLEMENTS` when the generated app target does not already point at an entitlements file | ||
|
|
||
| ## What you still need to host | ||
|
|
||
| You must publish `apple-app-site-association` on the relying-party domain: | ||
|
|
||
| ```text | ||
| https://signin.example.com/.well-known/apple-app-site-association | ||
| ``` | ||
|
|
||
| Example: | ||
|
|
||
| ```json | ||
| { | ||
| "webcredentials": { | ||
| "apps": ["ABCDE12345.app.capgo.passkey.example"] | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ## Checklist | ||
|
|
||
| 1. Set `origin` and `domains` in `plugins.CapacitorPasskey` in `capacitor.config.*`. | ||
| 2. Run `bunx cap sync`. | ||
| 3. Confirm your Apple Team ID and app bundle ID, then build the `TEAMID.bundleId` value for the association file. | ||
| 4. Host `apple-app-site-association` with HTTP `200` and no `.json` extension. | ||
| 5. Make sure the relying-party ID used by your backend matches the associated domain. | ||
|
|
||
| ## Notes | ||
|
|
||
| - The website file must be served from the exact passkey domain you use as the relying-party ID. | ||
| - On iOS 17.4 and newer, the plugin uses the browser-style client-data API so the configured HTTPS origin is reflected in `clientDataJSON`. | ||
| - The plugin can patch native project files during sync, but it cannot create or host the website association file on your domain. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.