Skip to content

Passkey slice 1: design record for passkey sign-in #1282

Open

Description

@mforce

Epic: #320 · Size: L · Needs: #1274

Context

See epic #320 for the verified facts. In short, .NET 10 ships passkeys as a primary factor behind SignInManager. This repo does not register SignInManager (src/Cluckwork.Api/Hosting/CluckworkIdentityServiceCollectionExtensions.cs:69-82). The passkey table is not mapped (PlatformBusinessRecords.cs:23). Identity 10 does not check attestation.

The maintainer decided passkeys are a login method only, for now: a user signs in with a passkey instead of a password. A passkey is not a step-up factor and not a second factor. #1274's decision record defines the login pending state. This record extends it and does not replace it.

The record must decide

  1. What a passkey sign-in proves. State what an attacker who holds the password alone, or the passkey alone, can do. Decided by the maintainer (2026-10-12): a passkey sign-in skips the TOTP code step. In exchange, the server requires user verification (the device unlock by fingerprint, face or PIN) on every passkey sign-in, and refuses an assertion without it. TOTP still applies to step-up. Every Owner still enrols TOTP under 2FA slice 8: every Owner must use two-factor authentication #1281, because step-up needs it.
  2. SignInManager. Register it and call its passkey methods (MakePasskeyCreationOptionsAsync and the others), or call IPasskeyHandler<TUser> / PasskeyHandler<TUser> directly from the hand-written path. Check that each method the choice needs works without cookie authentication, and cite the 10.0 source.
  3. Attestation. None, or verified against the FIDO metadata service, and what happens to an authenticator that fails it.
  4. Fido2.NET. Whether to use it, and for what. A new package passes CI: dependency-vulnerability and SAST gates #146's gate and goes in Directory.Packages.props with regenerated lock files (chore: adopt Central Package Management so a version bump is one file, not eight #684). The image build gains it too.
  5. Storage. Identity's schema version 3 table, or a table of our own. Its tenant guard follows 2FA slice 3: tenant guard on AspNetUserTokens and TOTP secret storage #1276. Name its ledger owner ([B] #514 slice 3: table-owner completeness, walked from the EF model #845) and its chronology class (Standardize business-record timestamps and chronological list ordering #819).
  6. The relying party ID and origins for a multi-farm deployment on one host, and how they come from configuration, not a hosting provider (AGENTS.md, "Host-agnostic repo").
  7. Step-up after a passkey sign-in. Step-up stays with the password or a TOTP code. Decide what a user who signs in with a passkey uses for step-up, and whether a user may hold a passkey without a password.
  8. Recovery. What recover-admin and an Owner's reset do to passkeys.
  9. The farm code. Passkey sign-in still selects the farm first. Decide whether the browser may offer passkeys before the farm code is entered (discoverable credentials), and how a passkey from farm A is refused at farm B.

Acceptance criteria

Activity

  1. added this to the Passkeys milestone on Oct 12, 2026
  2. added
    sliceThin vertical work item
    area:apiAPI/endpoint layer
    size:LSeveral days; wide blast radius or unresolved scope
    epic-320Passkeys (WebAuthn) as an authentication factor (#320)
    on Oct 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:apiAPI/endpoint layerepic-320Passkeys (WebAuthn) as an authentication factor (#320)priority:tier4Deferred or speculativesize:LSeveral days; wide blast radius or unresolved scopesliceThin vertical work item

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions