feat: passkey login support with e2e tests#88
Merged
antosubash merged 25 commits intomainfrom Apr 6, 2026
Merged
Conversation
- sm new project: scaffold vite.dev.config.ts so sm dev works out of the box - sm dev: fix vite invocation (vite dev → vite) and add --configLoader runner - sm doctor: fix PagesKeyPattern regex to match single-quoted Pages/index.ts keys - moduleHmrPlugin: fall back to src/modules/ path for scaffolded user projects - SM0052/SM0053 diagnostics: scope to SimpleModule.* host projects only so user projects with their own naming conventions are not falsely flagged - AgentExtensionsEmitter: remove early return that broke empty projects - SimpleModuleHostExtensions: register IHttpContextAccessor for EntityInterceptor - Directory.Build.props: guard PackageReadmeFile with Exists() to fix pack
…upport - Configure IdentityOptions.Stores.SchemaVersion = Version3 in UsersModule to opt into the AspNetUserPasskeys table (WebAuthn passkey support) - Configure IdentityPasskeyOptions from appsettings "Passkeys" section in UsersModule - Add Passkeys config sections to appsettings.json and appsettings.Development.json - Fix HostDbContextFactory to expose a minimal service provider with IdentityOptions via UseApplicationServiceProvider so EF design-time model creation picks up SchemaVersion - Add UseApplicationServiceProvider to AddModuleDbContext for runtime parity - Add migration AddPasskeySupport creating Users_AspNetUserPasskeys table - Add HostDbContextPasskeys.cs as a seam partial for future passkey customizations
…hanges Add `protected override Version SchemaVersion => IdentitySchemaVersions.Version3` to the HostDbContext partial — this compiles cleanly against Identity 10.0.3 and is the correct way to opt into the AspNetUserPasskeys table. Because SchemaVersion is now a compile-time constant on the class, the two IOptions workarounds are no longer needed: remove UseApplicationServiceProvider(sp) from ModuleDbContextOptionsBuilder (which would have applied the full app DI to every module DbContext) and revert the ServiceCollection + BuildServiceProvider block from HostDbContextFactory (design-time).
Adds the POST /api/passkeys/register/begin endpoint that calls MakePasskeyCreationOptionsAsync and returns WebAuthn creation options JSON. Also fixes test infrastructure: UsersDbContext now overrides SchemaVersion to Version3 so the EF model includes the AspNetUserPasskeys table, and the shared test factory now calls UseApplicationServiceProvider so IdentityOptions (including SchemaVersion) are accessible during model creation. Adds appsettings.Testing.json to configure ServerDomain = "localhost" for tests.
Adds the POST /api/passkeys/register/complete endpoint that calls PerformPasskeyAttestationAsync to validate WebAuthn attestation and stores the passkey. Catches InvalidOperationException (no challenge cookie) and PasskeyException (crypto failure) to return 400 instead of 500. Also adds PasskeyApiEndpointTests integration test class covering all four scenarios: RegisterBegin authenticated/unauthenticated and RegisterComplete unauthenticated/invalid-credential. Tests seed a real user (passkey-test-user-id) with CreateAuthenticatedClient targeting that user ID.
…isterCompleteEndpoint Replace undisposed StreamReader with a using block (leaveOpen: true) to avoid closing the framework-owned request body stream. PasskeyException confirmed present in .NET 10 Identity — catch block retained as-is.
Add PasskeyLoginBeginEndpoint, PasskeyLoginCompleteEndpoint, GetPasskeysEndpoint, and DeletePasskeyEndpoint with full integration test coverage (38 tests passing).
Adds transports field to the passkeys DTO and derives a human-readable device type hint (e.g. 'Built-in sensor', 'Security key (USB)') shown below the passkey name in the Manage Passkeys page.
The test-projects directory contains its own biome.json which conflicts with the root configuration. Since test-projects is already excluded from the files.includes scope, explicitly adding it as an ignore pattern prevents the nested root config error.
…vigations - serial mode + beforeEach cleanup eliminates shared-state races between tests - migrate credential ID via CDP WebAuthn.getCredentials after registration so the sign-in assertion works whether or not the credential was stored as a resident key - register route handlers before navigation so no request can slip through unintercepted - replace page.waitForTimeout(500) with try/catch on waitForURL for deterministic error reporting - fix auth.setup.ts to navigate directly to /Identity/Account/Login instead of clicking the missing "Log in" link on the landing page
Deploying simplemodule-website with
|
| Latest commit: |
1fc0e69
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://22bd129c.simplemodule-website.pages.dev |
| Branch Preview URL: | https://worktree-logical-frolicking.simplemodule-website.pages.dev |
Deploying simplemodule-docs with
|
| Latest commit: |
4bf1d6a
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://9ce2c7cd.simplemodule.pages.dev |
| Branch Preview URL: | https://worktree-logical-frolicking.simplemodule.pages.dev |
Auto-merge of PR #87 (type-safe routes) placed the SM0054 endpoint/view Route-const diagnostics outside the 'foreach (var module in data.Modules)' loop, leaving 'module' out of scope. Move them back inside the loop.
…m/antosubash/SimpleModule into worktree-logical-frolicking-spark
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
Key implementation details
IdentityPasskeyOptions.ServerDomaingates the feature — passkey UI is hidden when unsetPasskeyHelpers.ToBase64Urlshared between endpoints to avoid duplicationpasskeyEnabledprop is re-computed in the login POST error path so the passkey button stays visible after a failed password attemptallowCredentialsinjection via route interception because ASP.NET Identity may not requestresidentKey: required, making discoverable-credential flow unreliable in CDPTest plan
npx playwright test tests/smoke/users-account.spec.ts tests/flows/users-passkey.spec.ts— 9/9 passdotnet test— all integration tests pass/Identity/Account/Manage/Passkeys, register a passkey, sign out, use passkey to sign in