Developing Email Verification Authentication
Email verification is the second most common problem after "Forgot Password": email didn't arrive, went to spam, link expired, user clicked link on different device and doesn't understand why nothing happens. Most of these problems are solved at design stage, not after user complaints.
Two Verification Types and Their Differences
Magic Link — email with link that instantly authorizes user. No password. Convenient, but requires user to access email at login moment. Suitable for B2B tools where users are often at computer.
Email + OTP code — email with 6-digit code user enters in app. User opens app → requests code → switches to email → memorizes/copies code → returns to app → enters. More steps, but works without deep link infrastructure.
For mobile apps Magic Link is technically complex but gives better UX: tap link in email → system opens app via Universal Links (iOS) / App Links (Android) → user authorized.
Magic Link via Universal Links Implementation
iOS Universal Links require apple-app-site-association file (AASA) on domain. Placed at https://yourdomain.com/.well-known/apple-app-site-association without extension, content-type application/json. iOS loads this file at installation and caches it.
{
"applinks": {
"apps": [],
"details": [{
"appID": "TEAMID.com.yourcompany.app",
"paths": ["/auth/verify/*"]
}]
}
}
Email link: https://yourdomain.com/auth/verify/TOKEN. On iOS click — system checks AASA, if path matches — opens app via UIApplicationDelegate.application(_:continue:restorationHandler:) or onOpenURL in SwiftUI. App extracts token from URL, sends to backend, gets auth tokens.
On Android — App Links with assetlinks.json at https://yourdomain.com/.well-known/assetlinks.json. Intent Filter in manifest:
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="https" android:host="yourdomain.com" android:pathPrefix="/auth/verify/"/>
</intent-filter>
Critical edge case: user opened email on computer, clicked link — browser opened webpage, which should show "Return to app and sign in via code". Webpage generates same token in QR code or offers manual copy. Missing this scenario is a common mistake.
Another edge case: if AASA file unavailable at install time (server error) — Universal Links don't work, links open in browser. Need fallback: webpage with "Open in app" button via Custom URL Scheme (myapp://auth/verify/TOKEN) as backup.
Email Delivery: What Affects Deliverability
Email with code in "Spam" folder — conversion killer. Key factors:
- SPF, DKIM, DMARC — mandatory DNS records. Without them Gmail and Outlook aggressively filter.
- Transactional email provider — SendGrid, Postmark, Mailgun, Amazon SES. Not SMTP from own server — cold IP, zero reputation.
-
From-address — real domain, not
noreply@yourdomainwithout DMARC. Betterhello@yourdomain— fewer spam triggers. - Email text — shouldn't contain "FREE", "Click here to win", all caps. Only functional: "Your login code: 847293".
Token TTL: 15-30 minutes for OTP code, 1 hour for Magic Link. After use — immediately invalidate (single use). Store token hash, not token itself.
Timeline: 1 to 2 weeks. Includes both scenarios (Magic Link + OTP fallback), email provider setup, Universal Links / App Links, browser link opening edge case handling.







