DEV Community

ArshTechPro
ArshTechPro

Posted on • Edited on

Understanding Passkeys in SwiftUI: Part 1

What Are Passkeys?

Passkeys are cryptographic key pairs that replace passwords:

Private key - Stays on your device, stored in iCloud Keychain, syncs across your Apple devices
Public key - Sent to the server, stored instead of a password hash

When you sign in, your device creates a cryptographic signature with the private key (without revealing it). The server verifies this signature using the public key. Match = authenticated.

Unlike passwords where you send the same secret every time, passkeys prove you have the secret without transmitting it.

How Passkeys Work

The flow has two parts: registration (creating an account) and authentication (signing in). Both follow a challenge-response pattern that prevents replay attacks.

See the flow diagram:

Registration flow
Registration description

Sign in Flow
Sign in description

The challenge is critical - it's a random value that makes each authentication unique. Even if someone intercepts a signature, they can't reuse it because the next attempt uses a different challenge.

Why Passkeys Matter

Security wins:

  • No password reuse - Each passkey is unique to your domain
  • Phishing-proof - Passkeys only work on the exact domain they were created for
  • Server breaches don't matter - Public keys are useless without private keys

Better UX:

  • No password resets - Users can't forget their passkeys
  • Faster than passwords + MFA - Biometric auth is quicker and more secure

Real adoption:

  • 69% of users have at least one passkey (FIDO Alliance, 2025)
  • 4x higher sign-in success vs passwords (Google)
  • 97% sign-in success at scale (TikTok)

This isn't experimental anymore. It's production-ready.

What You Need

Server side:

  • WebAuthn/FIDO2 endpoints (libraries exist for Node.js, Python, Go, Java)
  • Four endpoints: registration challenge, registration verify, auth challenge, auth verify

iOS side:

  • iOS 16+
  • Associated domains configured
  • Valid domain with SSL certificate

Domain setup:

  • apple-app-site-association file at /.well-known/ path

Setting Up Associated Domains

Add to your entitlements:

<key>com.apple.developer.associated-domains</key>
<array>
    <string>webcredentials:myapp.example.com</string>
</array>
Enter fullscreen mode Exit fullscreen mode

Create /.well-known/apple-app-site-association on your server:

{
  "webcredentials": {
    "apps": ["TEAMID.com.yourcompany.yourapp"]
  }
}
Enter fullscreen mode Exit fullscreen mode

This links your app to your domain. Both sides must verify the relationship.

The Challenge-Response Pattern

Every auth action starts with the server generating a random challenge (16-32 bytes, base64-encoded). Used only once.

Your app passes the challenge to iOS with your domain and user ID. iOS prompts for Face ID/Touch ID, then uses the private key to sign the challenge. This signature proves possession of the private key without revealing it.

Your server verifies the signature using the stored public key. Valid signature = authenticated.

Challenges prevent replay attacks. An intercepted signature is useless for the next authentication because it'll have a different challenge.

What Happens on Device

iOS handles the heavy lifting:

  1. Checks device supports passkeys (Face ID/Touch ID + iCloud Keychain)
  2. Shows biometric prompt with your app name and domain
  3. On success, accesses Secure Enclave (hardware security chip)
  4. Generates signature with private key (key never leaves Secure Enclave)
  5. Returns credential/signature to your app

If multiple passkeys exist for your domain, iOS shows a picker. Your app never sees the private key.

iCloud Keychain Sync

Passkeys sync automatically across your Apple devices (end-to-end encrypted). Create once on iPhone, use on iPad and Mac.

Benefits:

  • Seamless multi-device access
  • Automatic backup when getting new devices
  • QR code sharing for non-Apple devices

Planning Your Implementation

Key decisions:

Onboarding timing:

  • During account creation (makes passkeys default)
  • After first password login (captures verified users)
  • In settings (user-controlled)

Fallback strategy:

  • Keep password auth during transition
  • Handle devices without Face ID/Touch ID
  • Support users who disabled iCloud Keychain

Backend changes:

  • New endpoints for WebAuthn
  • Database schema for public keys
  • User education about passkeys

Start by adding passkeys alongside passwords, not replacing them immediately.

Next: Implementation

Part 2 covers the actual code: SwiftUI views, authentication view model, error handling, and server integration. You'll have working passkey authentication you can adapt for your app.

Top comments (6)

Collapse
 
arshtechpro profile image
ArshTechPro

Passkeys are cryptographic key pairs that replace passwords:

Private key - Stays on your device, stored in iCloud Keychain, syncs across your Apple devices
Public key - Sent to the server, stored instead of a password hash

Collapse
 
olivia-john profile image
Olivia John

Awesome breakdown! Makes passkeys and passwordless sign-ins in SwiftUI way easier to understand.

Collapse
 
arshtechpro profile image
ArshTechPro

thanks for the appreciation

Collapse
 
olivia-john profile image
Olivia John

Really enjoying your articles (new here😊) - great stuff! When I checked out your page and saw “I like to keep it simple: if you’re curious, building something, or just feel like connecting…” I thought I’d reach out, but couldn’t seem to find a way to connect directly.

Thread Thread
 
arshtechpro profile image
ArshTechPro

Thanks for pointing it out. I added the link.

Collapse
 
hashbyt profile image
Hashbyt

This is an excellent, high-level overview of Passkeys and their architecture! I especially appreciate the clear explanation of the challenge-response pattern that prevents replay attacks.