From 4536462261b85c6ef7c43e7ae61419159acaa67a Mon Sep 17 00:00:00 2001 From: jhickmanit Date: Tue, 21 Apr 2026 08:35:41 -0700 Subject: [PATCH 1/6] docs(kratos): document passkey advanced configuration options Add an 'Advanced configuration' section under the dedicated passkey strategy that documents: - authenticator_selection (attachment, require_resident_key, user_verification) - attestation (preference, allow_none, allow_self, allow_untrusted) - timeouts (registration, login) Include a warning admonition explaining that disabling attestation.allow_none rejects most consumer passkeys, and add a three-tab example (Ory CLI, Ory Network, self-hosted Kratos) showing cross-platform attachment with required user verification. --- docs/kratos/passwordless/05_passkeys.mdx | 75 ++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/docs/kratos/passwordless/05_passkeys.mdx b/docs/kratos/passwordless/05_passkeys.mdx index 6d2dcad5c1..c21774f313 100644 --- a/docs/kratos/passwordless/05_passkeys.mdx +++ b/docs/kratos/passwordless/05_passkeys.mdx @@ -111,6 +111,81 @@ Alternatively, use the Ory CLI to enable the passkey strategy: ``` +### Advanced configuration + +The passkey strategy exposes additional options that control the WebAuthn ceremony and post-registration policy. All options are +optional. Defaults match the behavior before these options were introduced, so existing deployments do not need to change +anything. + +| Option | Type | Default | What it controls | +| ---------------------------------------------- | -------- | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | +| `authenticator_selection.attachment` | string | `"platform"` | Which authenticators are eligible: `"platform"` (Touch ID, Windows Hello), `"cross-platform"` (security keys), or `""` for no preference. | +| `authenticator_selection.require_resident_key` | boolean | `true` | Whether the authenticator must create a client-side discoverable credential. | +| `authenticator_selection.user_verification` | string | `"preferred"` | Whether biometrics or a PIN are required: `"required"`, `"preferred"`, or `"discouraged"`. | +| `attestation.preference` | string | `"none"` | Attestation conveyance preference sent to the authenticator: `"none"`, `"indirect"`, `"direct"`, or `"enterprise"`. | +| `attestation.allow_none` | boolean | `true` | Accept passkeys that provide no attestation statement. Most consumer passkeys, including iOS, use none attestation. | +| `attestation.allow_self` | boolean | `true` | Accept passkeys that provide a self-signed attestation statement with no external certificate authority. | +| `attestation.allow_untrusted` | boolean | `true` | Accept passkeys whose attestation certificate chain has no trusted root. | +| `timeouts.registration` | duration | library default (5m) | Timeout for the registration ceremony. Use Go duration format, for example `"60s"` or `"5m"`. | +| `timeouts.login` | duration | library default (5m) | Timeout for the login ceremony. Use Go duration format. | + +:::warning + +Disabling `attestation.allow_none` rejects most consumer passkeys. iOS does not support attestation at all, and Android and +Windows support it inconsistently. Only restrict attestation if your deployment requires attested authenticators, such as +FIDO-certified security keys in a regulated environment. The default configuration allows all attestation types so that any +standards-compliant passkey can register. + +::: + +The following example configures cross-platform authenticators (such as a HID token or YubiKey) with required user verification: + +```mdx-code-block + + + {`ory patch identity-config \\ + --add '/selfservice/methods/passkey/config/authenticator_selection/attachment="cross-platform"' \\ + --add '/selfservice/methods/passkey/config/authenticator_selection/user_verification="required"' +`} + + + + {`selfservice: + methods: + passkey: + enabled: true + config: + authenticator_selection: + attachment: cross-platform + user_verification: required`} + + + {`selfservice: + methods: + passkey: + enabled: true + config: + rp: + display_name: Your Application name + id: localhost + origins: + - http://localhost:4455 + authenticator_selection: + attachment: cross-platform + require_resident_key: true + user_verification: required + attestation: + preference: none + allow_none: true + allow_self: true + allow_untrusted: true + timeouts: + registration: 5m + login: 5m`} + + +``` + ### Identity schema If you want to use a custom identity schema, you must define which field of the identity schema is the display name for the From 9a98779525cf0d761103d4721984e3671e2680db Mon Sep 17 00:00:00 2001 From: jhickmanit Date: Wed, 22 Apr 2026 10:14:15 -0700 Subject: [PATCH 2/6] docs: update passkey options to match final Kratos API The Kratos PR moved to a simpler API shape after review: - resident_key enum replaces the require_resident_key boolean (values: required, preferred, discouraged; default required) - attestation.policy enum replaces the three allow_* booleans (values: allow_untrusted, allow_self, allow_none; default allow_untrusted) - authenticator_selection.attachment no longer defaults to "platform"; omit it to accept either platform or cross-platform authenticators Rewrite the warning admonition to match the new policy semantics and note that Kratos does not verify attestation certificate chains today, so "allow_self" and "allow_none" are opt-in stricter stances rather than cryptographic validation. Update the self-hosted example to use the new field names. --- docs/kratos/passwordless/05_passkeys.mdx | 43 ++++++++++++------------ 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/docs/kratos/passwordless/05_passkeys.mdx b/docs/kratos/passwordless/05_passkeys.mdx index c21774f313..c7b11e0698 100644 --- a/docs/kratos/passwordless/05_passkeys.mdx +++ b/docs/kratos/passwordless/05_passkeys.mdx @@ -114,27 +114,28 @@ Alternatively, use the Ory CLI to enable the passkey strategy: ### Advanced configuration The passkey strategy exposes additional options that control the WebAuthn ceremony and post-registration policy. All options are -optional. Defaults match the behavior before these options were introduced, so existing deployments do not need to change -anything. - -| Option | Type | Default | What it controls | -| ---------------------------------------------- | -------- | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | -| `authenticator_selection.attachment` | string | `"platform"` | Which authenticators are eligible: `"platform"` (Touch ID, Windows Hello), `"cross-platform"` (security keys), or `""` for no preference. | -| `authenticator_selection.require_resident_key` | boolean | `true` | Whether the authenticator must create a client-side discoverable credential. | -| `authenticator_selection.user_verification` | string | `"preferred"` | Whether biometrics or a PIN are required: `"required"`, `"preferred"`, or `"discouraged"`. | -| `attestation.preference` | string | `"none"` | Attestation conveyance preference sent to the authenticator: `"none"`, `"indirect"`, `"direct"`, or `"enterprise"`. | -| `attestation.allow_none` | boolean | `true` | Accept passkeys that provide no attestation statement. Most consumer passkeys, including iOS, use none attestation. | -| `attestation.allow_self` | boolean | `true` | Accept passkeys that provide a self-signed attestation statement with no external certificate authority. | -| `attestation.allow_untrusted` | boolean | `true` | Accept passkeys whose attestation certificate chain has no trusted root. | -| `timeouts.registration` | duration | library default (5m) | Timeout for the registration ceremony. Use Go duration format, for example `"60s"` or `"5m"`. | -| `timeouts.login` | duration | library default (5m) | Timeout for the login ceremony. Use Go duration format. | +optional. Defaults accept every standards-compliant passkey, so existing deployments do not need to change anything. + +| Option | Type | Default | What it controls | +| ------------------------------------------- | -------- | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `authenticator_selection.attachment` | string | _unset_ | Restricts eligible authenticators by attachment modality: `"platform"` (Touch ID, Windows Hello) or `"cross-platform"` (HID tokens, YubiKeys). Omit this field to accept either type. | +| `authenticator_selection.resident_key` | string | `"required"` | Whether the authenticator must create a client-side discoverable credential: `"required"`, `"preferred"`, or `"discouraged"`. | +| `authenticator_selection.user_verification` | string | `"preferred"` | Whether biometrics or a PIN are required: `"required"`, `"preferred"`, or `"discouraged"`. | +| `attestation.preference` | string | `"none"` | Attestation conveyance preference sent to the authenticator: `"none"`, `"indirect"`, `"direct"`, or `"enterprise"`. | +| `attestation.policy` | string | `"allow_untrusted"` | Which attestation types Kratos accepts after registration: `"allow_untrusted"` accepts any attestation, `"allow_self"` rejects credentials with unverifiable certificate chains, and `"allow_none"` only accepts credentials without an attestation statement. | +| `timeouts.registration` | duration | library default (5m) | Timeout for the registration ceremony. Use Go duration format, for example `"60s"` or `"5m"`. | +| `timeouts.login` | duration | library default (5m) | Timeout for the login ceremony. Use Go duration format. | :::warning -Disabling `attestation.allow_none` rejects most consumer passkeys. iOS does not support attestation at all, and Android and -Windows support it inconsistently. Only restrict attestation if your deployment requires attested authenticators, such as -FIDO-certified security keys in a regulated environment. The default configuration allows all attestation types so that any -standards-compliant passkey can register. +Setting `attestation.policy` to a value stricter than `"allow_untrusted"` rejects most consumer passkeys. iOS, Android, and most +password managers return no attestation statement by design, which the `"allow_none"` policy still accepts — but any +authenticator that does provide an attestation certificate chain is rejected under `"allow_self"`. Only restrict the policy if +your deployment has a clear requirement for attested authenticators. + +Kratos does not currently verify attestation certificate chains against a trust anchor (for example, the FIDO Metadata +Service). The `"allow_self"` and `"allow_none"` values are opt-in stricter stances, not cryptographic validation of +authenticator provenance. ::: @@ -172,13 +173,11 @@ The following example configures cross-platform authenticators (such as a HID to - http://localhost:4455 authenticator_selection: attachment: cross-platform - require_resident_key: true + resident_key: required user_verification: required attestation: preference: none - allow_none: true - allow_self: true - allow_untrusted: true + policy: allow_untrusted timeouts: registration: 5m login: 5m`} From 7e273fe5960102b9ddf72f6e1a8f6a146b5984e6 Mon Sep 17 00:00:00 2001 From: jhickmanit Date: Wed, 22 Apr 2026 10:15:15 -0700 Subject: [PATCH 3/6] docs: prettier --- docs/kratos/passwordless/05_passkeys.mdx | 28 ++++++++++++------------ 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/kratos/passwordless/05_passkeys.mdx b/docs/kratos/passwordless/05_passkeys.mdx index c7b11e0698..fcbe700182 100644 --- a/docs/kratos/passwordless/05_passkeys.mdx +++ b/docs/kratos/passwordless/05_passkeys.mdx @@ -116,26 +116,26 @@ Alternatively, use the Ory CLI to enable the passkey strategy: The passkey strategy exposes additional options that control the WebAuthn ceremony and post-registration policy. All options are optional. Defaults accept every standards-compliant passkey, so existing deployments do not need to change anything. -| Option | Type | Default | What it controls | -| ------------------------------------------- | -------- | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `authenticator_selection.attachment` | string | _unset_ | Restricts eligible authenticators by attachment modality: `"platform"` (Touch ID, Windows Hello) or `"cross-platform"` (HID tokens, YubiKeys). Omit this field to accept either type. | -| `authenticator_selection.resident_key` | string | `"required"` | Whether the authenticator must create a client-side discoverable credential: `"required"`, `"preferred"`, or `"discouraged"`. | -| `authenticator_selection.user_verification` | string | `"preferred"` | Whether biometrics or a PIN are required: `"required"`, `"preferred"`, or `"discouraged"`. | -| `attestation.preference` | string | `"none"` | Attestation conveyance preference sent to the authenticator: `"none"`, `"indirect"`, `"direct"`, or `"enterprise"`. | +| Option | Type | Default | What it controls | +| ------------------------------------------- | -------- | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `authenticator_selection.attachment` | string | _unset_ | Restricts eligible authenticators by attachment modality: `"platform"` (Touch ID, Windows Hello) or `"cross-platform"` (HID tokens, YubiKeys). Omit this field to accept either type. | +| `authenticator_selection.resident_key` | string | `"required"` | Whether the authenticator must create a client-side discoverable credential: `"required"`, `"preferred"`, or `"discouraged"`. | +| `authenticator_selection.user_verification` | string | `"preferred"` | Whether biometrics or a PIN are required: `"required"`, `"preferred"`, or `"discouraged"`. | +| `attestation.preference` | string | `"none"` | Attestation conveyance preference sent to the authenticator: `"none"`, `"indirect"`, `"direct"`, or `"enterprise"`. | | `attestation.policy` | string | `"allow_untrusted"` | Which attestation types Kratos accepts after registration: `"allow_untrusted"` accepts any attestation, `"allow_self"` rejects credentials with unverifiable certificate chains, and `"allow_none"` only accepts credentials without an attestation statement. | -| `timeouts.registration` | duration | library default (5m) | Timeout for the registration ceremony. Use Go duration format, for example `"60s"` or `"5m"`. | -| `timeouts.login` | duration | library default (5m) | Timeout for the login ceremony. Use Go duration format. | +| `timeouts.registration` | duration | library default (5m) | Timeout for the registration ceremony. Use Go duration format, for example `"60s"` or `"5m"`. | +| `timeouts.login` | duration | library default (5m) | Timeout for the login ceremony. Use Go duration format. | :::warning Setting `attestation.policy` to a value stricter than `"allow_untrusted"` rejects most consumer passkeys. iOS, Android, and most -password managers return no attestation statement by design, which the `"allow_none"` policy still accepts — but any -authenticator that does provide an attestation certificate chain is rejected under `"allow_self"`. Only restrict the policy if -your deployment has a clear requirement for attested authenticators. +password managers return no attestation statement by design, which the `"allow_none"` policy still accepts — but any authenticator +that does provide an attestation certificate chain is rejected under `"allow_self"`. Only restrict the policy if your deployment +has a clear requirement for attested authenticators. -Kratos does not currently verify attestation certificate chains against a trust anchor (for example, the FIDO Metadata -Service). The `"allow_self"` and `"allow_none"` values are opt-in stricter stances, not cryptographic validation of -authenticator provenance. +Kratos does not currently verify attestation certificate chains against a trust anchor (for example, the FIDO Metadata Service). +The `"allow_self"` and `"allow_none"` values are opt-in stricter stances, not cryptographic validation of authenticator +provenance. ::: From e17e24e97505325193a30b3563153265ad4f5cce Mon Sep 17 00:00:00 2001 From: jhickmanit Date: Fri, 24 Apr 2026 13:24:53 -0700 Subject: [PATCH 4/6] docs: drop passkey attestation.policy section Policy knob was removed from the Kratos PR because Kratos has no trust-anchor verification, so strict policy levels did not provide cryptographic validation. Docs now only describe the ceremony options that shipped: authenticator_selection, attestation.preference, timeouts. --- docs/kratos/passwordless/05_passkeys.mdx | 37 +++++++----------------- 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/docs/kratos/passwordless/05_passkeys.mdx b/docs/kratos/passwordless/05_passkeys.mdx index fcbe700182..469045f952 100644 --- a/docs/kratos/passwordless/05_passkeys.mdx +++ b/docs/kratos/passwordless/05_passkeys.mdx @@ -113,31 +113,17 @@ Alternatively, use the Ory CLI to enable the passkey strategy: ### Advanced configuration -The passkey strategy exposes additional options that control the WebAuthn ceremony and post-registration policy. All options are -optional. Defaults accept every standards-compliant passkey, so existing deployments do not need to change anything. - -| Option | Type | Default | What it controls | -| ------------------------------------------- | -------- | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `authenticator_selection.attachment` | string | _unset_ | Restricts eligible authenticators by attachment modality: `"platform"` (Touch ID, Windows Hello) or `"cross-platform"` (HID tokens, YubiKeys). Omit this field to accept either type. | -| `authenticator_selection.resident_key` | string | `"required"` | Whether the authenticator must create a client-side discoverable credential: `"required"`, `"preferred"`, or `"discouraged"`. | -| `authenticator_selection.user_verification` | string | `"preferred"` | Whether biometrics or a PIN are required: `"required"`, `"preferred"`, or `"discouraged"`. | -| `attestation.preference` | string | `"none"` | Attestation conveyance preference sent to the authenticator: `"none"`, `"indirect"`, `"direct"`, or `"enterprise"`. | -| `attestation.policy` | string | `"allow_untrusted"` | Which attestation types Kratos accepts after registration: `"allow_untrusted"` accepts any attestation, `"allow_self"` rejects credentials with unverifiable certificate chains, and `"allow_none"` only accepts credentials without an attestation statement. | -| `timeouts.registration` | duration | library default (5m) | Timeout for the registration ceremony. Use Go duration format, for example `"60s"` or `"5m"`. | -| `timeouts.login` | duration | library default (5m) | Timeout for the login ceremony. Use Go duration format. | - -:::warning - -Setting `attestation.policy` to a value stricter than `"allow_untrusted"` rejects most consumer passkeys. iOS, Android, and most -password managers return no attestation statement by design, which the `"allow_none"` policy still accepts — but any authenticator -that does provide an attestation certificate chain is rejected under `"allow_self"`. Only restrict the policy if your deployment -has a clear requirement for attested authenticators. - -Kratos does not currently verify attestation certificate chains against a trust anchor (for example, the FIDO Metadata Service). -The `"allow_self"` and `"allow_none"` values are opt-in stricter stances, not cryptographic validation of authenticator -provenance. - -::: +The passkey strategy exposes additional options that control the WebAuthn ceremony. All options are optional. Defaults accept +every standards-compliant passkey, so existing deployments do not need to change anything. + +| Option | Type | Default | What it controls | +| ------------------------------------------- | -------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `authenticator_selection.attachment` | string | _unset_ | Restricts eligible authenticators by attachment modality: `"platform"` (Touch ID, Windows Hello) or `"cross-platform"` (HID tokens, YubiKeys). Omit this field to accept either type. | +| `authenticator_selection.resident_key` | string | `"required"` | Whether the authenticator must create a client-side discoverable credential: `"required"`, `"preferred"`, or `"discouraged"`. | +| `authenticator_selection.user_verification` | string | `"preferred"` | Whether biometrics or a PIN are required: `"required"`, `"preferred"`, or `"discouraged"`. | +| `attestation.preference` | string | `"none"` | Attestation conveyance preference sent to the authenticator: `"none"`, `"indirect"`, `"direct"`, or `"enterprise"`. | +| `timeouts.registration` | duration | library default (5m) | Timeout for the registration ceremony. Use Go duration format, for example `"60s"` or `"5m"`. | +| `timeouts.login` | duration | library default (5m) | Timeout for the login ceremony. Use Go duration format. | The following example configures cross-platform authenticators (such as a HID token or YubiKey) with required user verification: @@ -177,7 +163,6 @@ The following example configures cross-platform authenticators (such as a HID to user_verification: required attestation: preference: none - policy: allow_untrusted timeouts: registration: 5m login: 5m`} From 942fafe1af1f29e2ccb7b435cc0afa7f09b3216b Mon Sep 17 00:00:00 2001 From: jhickmanit Date: Thu, 4 Jun 2026 09:34:04 -0700 Subject: [PATCH 5/6] docs: reconcile passkey advanced config with shipped Kratos API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds the missing default-behavior callout (attachment was hardcoded "platform", now defaults to no preference) and clarifies that attestation.preference is request-only — Kratos does not verify or enforce the returned attestation statement. Also corrects the timeouts defaults (5m with user verification, 2m without). Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/kratos/passwordless/05_passkeys.mdx | 34 ++++++++++++++++++------ 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/docs/kratos/passwordless/05_passkeys.mdx b/docs/kratos/passwordless/05_passkeys.mdx index 469045f952..fe4f113c23 100644 --- a/docs/kratos/passwordless/05_passkeys.mdx +++ b/docs/kratos/passwordless/05_passkeys.mdx @@ -116,14 +116,32 @@ Alternatively, use the Ory CLI to enable the passkey strategy: The passkey strategy exposes additional options that control the WebAuthn ceremony. All options are optional. Defaults accept every standards-compliant passkey, so existing deployments do not need to change anything. -| Option | Type | Default | What it controls | -| ------------------------------------------- | -------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `authenticator_selection.attachment` | string | _unset_ | Restricts eligible authenticators by attachment modality: `"platform"` (Touch ID, Windows Hello) or `"cross-platform"` (HID tokens, YubiKeys). Omit this field to accept either type. | -| `authenticator_selection.resident_key` | string | `"required"` | Whether the authenticator must create a client-side discoverable credential: `"required"`, `"preferred"`, or `"discouraged"`. | -| `authenticator_selection.user_verification` | string | `"preferred"` | Whether biometrics or a PIN are required: `"required"`, `"preferred"`, or `"discouraged"`. | -| `attestation.preference` | string | `"none"` | Attestation conveyance preference sent to the authenticator: `"none"`, `"indirect"`, `"direct"`, or `"enterprise"`. | -| `timeouts.registration` | duration | library default (5m) | Timeout for the registration ceremony. Use Go duration format, for example `"60s"` or `"5m"`. | -| `timeouts.login` | duration | library default (5m) | Timeout for the login ceremony. Use Go duration format. | +| Option | Type | Default | What it controls | +| ------------------------------------------- | -------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `authenticator_selection.attachment` | string | _unset_ | Restricts eligible authenticators by attachment modality: `"platform"` (Touch ID, Windows Hello) or `"cross-platform"` (HID tokens, YubiKeys). Omit this field to accept either type. | +| `authenticator_selection.resident_key` | string | `"required"` | Whether the authenticator must create a client-side discoverable credential: `"required"`, `"preferred"`, or `"discouraged"`. | +| `authenticator_selection.user_verification` | string | `"preferred"` | Whether biometrics or a PIN are required: `"required"`, `"preferred"`, or `"discouraged"`. | +| `attestation.preference` | string | `"none"` | Attestation conveyance preference Kratos _requests_ from the authenticator: `"none"`, `"indirect"`, `"direct"`, or `"enterprise"`. See the note below — this is a request hint only, not an enforcement control. | +| `timeouts.registration` | duration | library default | Timeout for the registration ceremony. Use Go duration format, for example `"60s"` or `"5m"`. When unset, the library default applies: 5 minutes with user verification, 2 minutes without. | +| `timeouts.login` | duration | library default | Timeout for the login ceremony. Use Go duration format. When unset, the same default behavior as `timeouts.registration` applies. | + +:::note + +**Default behavior change:** Earlier versions of the passkey strategy hardcoded `attachment: platform`, so only built-in +authenticators (Touch ID, Windows Hello) could be registered. The strategy now defaults to **no attachment preference**, which +means users can register either platform or cross-platform (roaming) authenticators. To restore the previous behavior, set +`authenticator_selection.attachment` to `"platform"`. + +::: + +:::note + +**`attestation.preference` is request-only:** This option controls only what Kratos requests from the authenticator. Kratos does +not verify or enforce the returned attestation statement, so this option cannot be used to restrict registration to specific +authenticator types or models. Most consumer passkeys (iOS, Android) support only `"none"`; requesting `"direct"` or +`"enterprise"` may not be honored. + +::: The following example configures cross-platform authenticators (such as a HID token or YubiKey) with required user verification: From 96a40009b44d893b4020d7f12946f3c8928c652f Mon Sep 17 00:00:00 2001 From: jhickmanit Date: Fri, 5 Jun 2026 12:31:01 -0700 Subject: [PATCH 6/6] docs: clarify passkey timeout enforcement and soften advanced-config intro - Note that timeouts.registration/login are browser-enforced; flow lifespans govern server-side validity - Reword section intro so it no longer contradicts the attachment default-change note - Precise wording for the library default timeout values Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/kratos/passwordless/05_passkeys.mdx | 30 +++++++++++++++--------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/docs/kratos/passwordless/05_passkeys.mdx b/docs/kratos/passwordless/05_passkeys.mdx index 4b102205ef..c83722198f 100644 --- a/docs/kratos/passwordless/05_passkeys.mdx +++ b/docs/kratos/passwordless/05_passkeys.mdx @@ -113,17 +113,17 @@ Alternatively, use the Ory CLI to enable the passkey strategy: ### Advanced configuration -The passkey strategy exposes additional options that control the WebAuthn ceremony. All options are optional. Defaults accept -every standards-compliant passkey, so existing deployments do not need to change anything. - -| Option | Type | Default | What it controls | -| ------------------------------------------- | -------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `authenticator_selection.attachment` | string | _unset_ | Restricts eligible authenticators by attachment modality: `"platform"` (Touch ID, Windows Hello) or `"cross-platform"` (HID tokens, YubiKeys). Omit this field to accept either type. | -| `authenticator_selection.resident_key` | string | `"required"` | Whether the authenticator must create a client-side discoverable credential: `"required"`, `"preferred"`, or `"discouraged"`. | -| `authenticator_selection.user_verification` | string | `"preferred"` | Whether biometrics or a PIN are required: `"required"`, `"preferred"`, or `"discouraged"`. | -| `attestation.preference` | string | `"none"` | Attestation conveyance preference Kratos _requests_ from the authenticator: `"none"`, `"indirect"`, `"direct"`, or `"enterprise"`. See the note below — this is a request hint only, not an enforcement control. | -| `timeouts.registration` | duration | library default | Timeout for the registration ceremony. Use Go duration format, for example `"60s"` or `"5m"`. When unset, the library default applies: 5 minutes with user verification, 2 minutes without. | -| `timeouts.login` | duration | library default | Timeout for the login ceremony. Use Go duration format. When unset, the same default behavior as `timeouts.registration` applies. | +The passkey strategy exposes additional options that control the WebAuthn ceremony. All options are optional and existing passkey +credentials keep working. One default changed — see the note on authenticator attachment below. + +| Option | Type | Default | What it controls | +| ------------------------------------------- | -------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `authenticator_selection.attachment` | string | _unset_ | Restricts eligible authenticators by attachment modality: `"platform"` (Touch ID, Windows Hello) or `"cross-platform"` (HID tokens, YubiKeys). Omit this field to accept either type. | +| `authenticator_selection.resident_key` | string | `"required"` | Whether the authenticator must create a client-side discoverable credential: `"required"`, `"preferred"`, or `"discouraged"`. | +| `authenticator_selection.user_verification` | string | `"preferred"` | Whether biometrics or a PIN are required: `"required"`, `"preferred"`, or `"discouraged"`. | +| `attestation.preference` | string | `"none"` | Attestation conveyance preference Kratos _requests_ from the authenticator: `"none"`, `"indirect"`, `"direct"`, or `"enterprise"`. See the note below — this is a request hint only, not an enforcement control. | +| `timeouts.registration` | duration | library default | Timeout for the registration ceremony. Use Go duration format, for example `"60s"` or `"5m"`. When unset, the library default applies: 5 minutes, or 2 minutes when `user_verification` is set to `"discouraged"`. | +| `timeouts.login` | duration | library default | Timeout for the login ceremony. Use Go duration format. When unset, the same default behavior as `timeouts.registration` applies. | :::note @@ -136,6 +136,14 @@ means users can register either platform or cross-platform (roaming) authenticat :::note +**Timeouts are enforced by the browser:** `timeouts.registration` and `timeouts.login` are communicated to the browser, which +enforces them during the WebAuthn ceremony. Kratos does not reject late responses server-side based on these values — the login +and registration flow lifespans (`selfservice.flows.*.lifespan`) govern how long a flow remains valid. + +::: + +:::note + **`attestation.preference` is request-only:** This option controls only what Kratos requests from the authenticator. Kratos does not verify or enforce the returned attestation statement, so this option cannot be used to restrict registration to specific authenticator types or models. Most consumer passkeys (iOS, Android) support only `"none"`; requesting `"direct"` or