ASP.NET Core  

Two-Factor Authentication (2FA) and Passkey Authentication in ASP.NET Core

2fa passkey

Modern web applications must protect user accounts from password theft, phishing, and credential-stuffing attacks. One of the most effective ways to strengthen authentication security is by implementing Two-Factor Authentication (2FA) .

In addition to traditional 2FA methods such as email codes, SMS codes, and authenticator apps, modern applications are increasingly adopting Passkeys, which enable passwordless authentication based on the FIDO2/WebAuthn standard.

2fa hybrid

Hybrid Authentication Process: A unified workflow supporting both traditional password-based entry with optional 2FA and modern, direct passkey login for a secure user experience.

Why Two-Factor Authentication Matters

Passwords alone are no longer sufficient for securing accounts. Attackers frequently obtain passwords through phishing, database leaks, or brute-force attacks.

Two-Factor Authentication (2FA) introduces a second verification factor, typically categorized as:

  • Something you know – Password or PIN

  • Something you have – Phone, authenticator app, security key

  • Something you are – Biometrics such as fingerprint or Face ID

With 2FA enabled, even if a password is compromised, attackers cannot access the account without the second factor.

2fa

Two-Factor Authentication Flow: A multi-layered security process requiring a secondary OTP verification step to ensure protected user access.

2FA Methods in ASP.NET Core

ASP.NET Core Identity provides built-in support for several 2FA mechanisms:

  • Email verification codes

  • SMS verification codes

  • Authenticator apps (TOTP)

  • Recovery codes

During login, if 2FA is enabled, the authentication process is split into two steps.

Step 1 — Username & Password Login

  
    var result = await _signInManager.PasswordSignInAsync(
    model.Email,
    model.Password,
    model.RememberMe,
    lockoutOnFailure: true
);

if (result.RequiresTwoFactor)
{
    return RedirectToAction("VerifyCode");
}
  

If the user has 2FA enabled, the login flow redirects to the verification step.

Step 2 — Verify the 2FA Code

ASP.NET Core Identity can generate verification tokens using different providers such as email, SMS, or authenticator apps.

  
    var code = await _userManager.GenerateTwoFactorTokenAsync(user, "Email");
  

This code is sent to the user through the selected provider.

To verify the code:

  
    var result = await _userManager.VerifyTwoFactorTokenAsync(
    user,
    _userManager.Options.Tokens.AuthenticatorTokenProvider,
    "Email",
    code
);
  

Authenticator App Setup (TOTP)

Authenticator apps such as:

  • Google Authenticator

  • Microsoft Authenticator

  • Authy

generate time-based one-time passwords (TOTP).

When enabling authenticator-based 2FA, the system generates a secret key and displays a QR code.

  
    var authenticatorKey = await _userManager.GetAuthenticatorKeyAsync(user);
if (string.IsNullOrEmpty(authenticatorKey))
{
    await _userManager.ResetAuthenticatorKeyAsync(user);
    authenticatorKey = await _userManager.GetAuthenticatorKeyAsync(user);
}
  

The QR code is then scanned by the authenticator app, allowing it to generate rotating verification codes every 30 seconds.

Recovery Codes

Recovery codes allow users to log in when they lose access to their authenticator device.

  
    var recoveryCodes = await _userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, 10);
  

These codes should be stored securely by the user.

Introducing Passkeys (Passwordless Authentication)

While traditional 2FA strengthens security, the industry is moving toward passwordless authentication using passkeys .

Passkeys are based on the FIDO2 / WebAuthn standard and use public-key cryptography instead of passwords.

Passkey

Passkey Authentication Flow: A secure, passwordless journey leveraging WebAuthn and biometric verification to ensure unphishable user access.

When a passkey is created:

  • A private key is stored securely on the user’s device.

  • A public key is stored on the server.

During login, the server sends a cryptographic challenge that can only be signed using the user's private key.

This makes phishing attacks extremely difficult because the private key never leaves the user's device.

Passkeys vs 2FA

Feature2FAPasskey
Password requiredYesNo
User experienceMulti-step loginSingle step
Security modelShared secretsPublic-key cryptography
Phishing resistanceModerateVery high
Device integrationAuthenticator appsBiometrics, device security

Passkeys in ASP.NET Core

ASP.NET Core supports passkey authentication based on the FIDO2 / WebAuthn standard , enabling modern, passwordless, and phishing-resistant authentication mechanisms.

The implementation can be achieved using the Fido2.AspNet package, which is available on NuGet and provides a ready-to-use library for integrating passkey registration and authentication flows into ASP.NET Core applications.

  
    dotnet add package Fido2.AspNet --version 4.0.0
  

Basic registration flow:

  • User clicks Register Passkey

  • Server generates a WebAuthn challenge

  • Browser prompts biometric verification

  • Device creates a cryptographic key pair

  • Public key is stored on the server

Login flow:

  • User selects Sign in with Passkey

  • Browser prompts biometric verification

  • Device signs the challenge using private key

  • Server validates the signature

Security Best Practices

When implementing authentication systems in ASP.NET Core, follow these recommendations:

  • Enable account lockout after multiple failed attempts

  • Require email confirmation

  • Store recovery codes securely

  • Enforce HTTPS

  • Log authentication events

  • Allow users to manage 2FA/passkey methods from a dashboard

Conclusion

Two-Factor Authentication significantly improves account security by requiring additional verification beyond passwords. ASP.NET Core Identity provides built-in support for implementing multiple 2FA methods including email, SMS, and authenticator apps.

However, the future of authentication is shifting toward passwordless systems like passkeys , which offer stronger protection against phishing and credential theft while improving user experience.

By combining 2FA with passkey authentication , developers can build modern, secure, and user-friendly authentication systems.

Demo Project

You can explore the complete working example here:

https://github.com/TechPdo/TwoFactorAuth

The project demonstrates how to build a production-style authentication system in ASP.NET Core MVC with 2FA support and extensibility for modern authentication methods like passkeys .