Why Go Passwordless in 2026?

Passwords are the weakest link in consumer authentication. Over 80% of data breaches involve stolen or weak credentials. In 2026, users expect seamless, frictionless login — and passwordless auth delivers exactly that while simultaneously raising your security baseline.

The case for passwordless B2C authentication is stronger than ever:

  • No credential stuffing attacks. There are no passwords to steal, reuse, or crack across breached databases.
  • Zero password reset tickets. Forgotten passwords are the #1 driver of auth-related support volume — eliminate the problem entirely.
  • Higher conversion rates. Frictionless login reduces sign-up and sign-in drop-off — particularly on mobile where typing passwords is painful.
  • Phishing resistance. Passkeys are origin-bound and cryptographically phishing-resistant. Magic links are single-use and link-scoped.
  • Universal platform support. In 2026, passkeys are supported natively on all major browsers, iOS 16+, Android 9+, macOS Ventura+, and Windows 11.

Passkeys & WebAuthn / FIDO2

Passkeys are the gold standard for passwordless authentication in 2026. Built on the WebAuthn (W3C) and FIDO2 standards, passkeys use public-key cryptography tied to a user's device — and optionally synced across iCloud Keychain, Google Password Manager, or a hardware security key.

How Passkeys Work

Registration:

  1. Your server sends a challenge (random bytes) to the browser.
  2. The browser calls navigator.credentials.create(), invoking the device authenticator (Face ID, Touch ID, Windows Hello, or a hardware key).
  3. The authenticator generates a new public/private key pair scoped to your origin (auth.ailacs.com). The private key never leaves the device.
  4. The browser returns the public key + attestation to your server, which stores it against the user account.

Authentication:

  1. Server sends a new random challenge.
  2. Browser calls navigator.credentials.get() — device prompts for biometric/PIN verification.
  3. Authenticator signs the challenge with the stored private key.
  4. Server verifies the signature against the stored public key — identity confirmed, no password required.

Passkey Platform Support in 2026

Platform Sync Support Hardware Key Notes
Chrome / Edge (Desktop) ✅ Google Password Manager or iCloud ✅ FIDO2 USB/NFC Full WebAuthn Level 3
Safari (macOS / iOS 16+) ✅ iCloud Keychain Best UX on Apple ecosystem
Firefox ⚠️ Limited sync (no native store) Works, but no built-in passkey sync
Android (Chrome) ✅ Google Password Manager ✅ NFC keys Full support since Android 9+
Windows 11 (Windows Hello) ✅ Windows Credential Manager Fingerprint / PIN / Face Recognition

WebAuthn Registration (JavaScript)

// Step 1: Fetch challenge and options from your server
const response = await fetch('/auth/passkey/register/begin', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ username: userEmail })
});
const options = await response.json();

// Step 2: Decode base64url fields
options.challenge = base64urlToUint8Array(options.challenge);
options.user.id   = base64urlToUint8Array(options.user.id);

// Step 3: Create credential — triggers device biometric/PIN prompt
const credential = await navigator.credentials.create({ publicKey: options });

// Step 4: Send attestation back to server for verification and storage
await fetch('/auth/passkey/register/complete', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
        id:   credential.id,
        rawId: uint8ArrayToBase64url(new Uint8Array(credential.rawId)),
        response: {
            clientDataJSON:  uint8ArrayToBase64url(
                new Uint8Array(credential.response.clientDataJSON)),
            attestationObject: uint8ArrayToBase64url(
                new Uint8Array(credential.response.attestationObject))
        },
        type: credential.type
    })
});

For production, use a battle-tested WebAuthn server library such as Fido2NetLib (.NET), SimpleWebAuthn (Node.js), or py_webauthn (Python) rather than hand-rolling the attestation verification logic.

TOTP Authenticator Apps (RFC 6238)

TOTP (Time-based One-Time Password, RFC 6238) is the technology behind authenticator apps like Google Authenticator, Microsoft Authenticator, and Authy. A 6-digit code rotates every 30 seconds, derived from a shared secret and the current Unix timestamp.

TOTP is most commonly used as a second factor (MFA) rather than as a standalone credential, but in a passwordless flow it can serve as the primary authentication factor when combined with a previously verified email address at registration.

TOTP Setup (.NET / ASP.NET Core Identity)

ASP.NET Core Identity has built-in TOTP MFA support. The IUserTwoFactorTokenProvider<TUser> interface handles code generation and verification via GenerateTwoFactorTokenAsync and VerifyTwoFactorTokenAsync.

// 1. Enable TOTP in Program.cs
builder.Services.AddIdentity<ApplicationUser, ApplicationRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders();

// 2. Display QR code to the user (setup page model)
public async Task OnGetAsync()
{
    var user = await _userManager.GetUserAsync(User);
    var key  = await _userManager.GetAuthenticatorKeyAsync(user);

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

    SharedKey      = FormatKey(key);
    AuthenticatorUri = $"otpauth://totp/{Uri.EscapeDataString("Ailacs Identity")}"
                     + $":{Uri.EscapeDataString(user.Email)}"
                     + $"?secret={key}&issuer=AilacsIdentity&digits=6&period=30";
}

// 3. Verify the code the user enters
public async Task<IActionResult> OnPostAsync()
{
    var user  = await _userManager.GetUserAsync(User);
    var valid = await _userManager.VerifyTwoFactorTokenAsync(
        user,
        _userManager.Options.Tokens.AuthenticatorTokenProvider,
        Input.Code.Replace(" ", "").Replace("-", ""));

    if (!valid)
    {
        ModelState.AddModelError("Input.Code", "Verification code is invalid.");
        return Page();
    }

    await _userManager.SetTwoFactorEnabledAsync(user, true);
    return RedirectToPage("./TwoFactorAuthentication");
}

Security Comparison: Passwordless Methods

Not all passwordless methods are equal. Here is how each compares across key security and UX dimensions:

Method Phishing Resistant Replay Protection Device Binding UX Friction Best For
Passkeys (WebAuthn/FIDO2) ✅ Origin-bound ✅ Cryptographic ✅ Device-bound ⭐ Very Low Consumer apps, enterprise
TOTP (Authenticator App) ⚠️ Partial (real-time phishing risk) ✅ 30 s window ⚠️ App-level only Medium MFA for B2C & B2B
Magic Links ⚠️ Link-scoped only ✅ Single-use token ❌ None Low Low-risk consumer flows
SMS OTP ❌ SIM-swap vulnerable ⚠️ Short window only ❌ None Low Legacy — avoid if possible

Security ranking from strongest to weakest: Passkeys > TOTP > Magic Links > SMS OTP. Always prefer the highest-security method available on the user's device.

Enabling Passwordless with Ailacs Identity

Ailacs Identity provides built-in support for all three passwordless methods. Enable and configure them in the tenant dashboard under Authentication → Passwordless.

✉️
Magic Links

Enable under Passwordless → Email Magic Link. Configure expiry (1–60 min) and per-address rate limits per tenant.

🔑
Passkeys

Enable under Passwordless → Passkeys (WebAuthn). Set RP ID to your domain. Supports both platform and roaming (hardware) authenticators.

📱
TOTP MFA

Enable under MFA → Authenticator App (TOTP). Works with Google Authenticator, Microsoft Authenticator, Authy, and any RFC 6238 app.

UX Best Practices for Passwordless B2C

  • Always offer a fallback. If passkey creation fails (new device, unsupported browser), fall back to magic link or TOTP. Never leave users stranded on a dead-end screen.
  • Progressive passkey enrollment. Don't force passkey setup at first login. Prompt after the user's second or third session — conversion is higher once users have invested in your product.
  • Clear magic link messaging. Tell users exactly which address the link was sent to, how long it is valid, and that it is single-use. Proactive messaging eliminates the most common support tickets.
  • Cross-device passkey flows. Support QR-code cross-device authentication (CTAP2) so users can authenticate on a desktop browser using their phone as an authenticator.
  • Secure account recovery. Always provide a recovery flow (verified email + identity challenge) for users who lose their passkey device or delete their authenticator app. Without this, passwordless becomes an account lockout risk.
  • Show the right option first. Detect passkey availability via PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable() and surface that method first. Hide or deprioritise methods the device cannot support.