Add passkey / biometric login (WebAuthn FIDO2)
Shop floor workers can log in once with a password, enroll a passkey, and use Face ID / Windows Hello / fingerprint for all future logins. - UserPasskey entity + AddUserPasskeys migration (Fido2 v4.0.1) - PasskeyController: RegisterOptions, Register, LoginOptions, Login, Manage, Remove endpoints - Login page: platform-aware button (Face ID / Windows Hello / etc.) hidden automatically if browser doesn't support WebAuthn - Post-login floating prompt to enroll on first use; session-dismissed - Passkeys & Biometrics link in user dropdown menu - Manage page: list registered devices, add new, remove individual - passkey.js: targeted base64url conversion (only challenge + user.id + credential IDs) — fixes "Required parameters missing" error caused by blindly converting rp.id and other string fields to ArrayBuffers Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -385,6 +385,13 @@ public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
|
||||
/// </summary>
|
||||
public DbSet<PendingRegistrationSession> PendingRegistrationSessions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// WebAuthn passkey credentials registered by users for biometric login (Face ID, fingerprint).
|
||||
/// No global query filter — the login flow queries by credentialId before authentication,
|
||||
/// requiring cross-tenant lookup. Per-user isolation is enforced in the controller.
|
||||
/// </summary>
|
||||
public DbSet<UserPasskey> UserPasskeys { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Configures the EF Core model: applies entity type configurations from the assembly,
|
||||
/// registers global query filters, defines relationships, adds performance indexes, and seeds
|
||||
@@ -792,9 +799,14 @@ public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
|
||||
property.SetColumnType("decimal(18,2)");
|
||||
}
|
||||
|
||||
// UserPasskey: unique index on CredentialId (WebAuthn requires global uniqueness)
|
||||
modelBuilder.Entity<UserPasskey>()
|
||||
.HasIndex(p => p.CredentialId)
|
||||
.IsUnique();
|
||||
|
||||
// Configure relationships
|
||||
ConfigureRelationships(modelBuilder);
|
||||
|
||||
|
||||
// Seed initial data
|
||||
SeedInitialData(modelBuilder);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user