Developing Password Recovery System in Mobile App
Password recovery — one of most vulnerable flows from security perspective. Yet often implemented carelessly: "sent email — not our responsibility next". Reality is mobile side bears responsibility for several critical moments.
Vulnerabilities often missed
User enumeration. Form "Enter email" should not reveal if address registered. Message "If email registered, we'll send letter" — standard practice. Message "No such user" — account info disclosure. Some projects consider this minor — but with GDPR this potentially problematic.
Rate limiting on client. "Resend" button should be disabled for 60–120 seconds after click. Without this user (or script) can spam-bomb someone else's email with recovery letters. Rate limiting needed on server too, but client shouldn't facilitate attack.
Deep link security. Recovery link like myapp://reset-password?token=xyz — must handle correctly. On Android without configured App Links with Digital Asset Links, any app can intercept custom scheme. Use HTTPS Universal Links (iOS) and HTTPS App Links (Android).
Main flow
- User enters email → "Recover" button (disabled until valid email).
- Request to server → show "Check email" regardless result (no user enumeration).
- Email has one-time token link and
expires_in(usually 15–60 minutes). - User taps link → app opens via Universal/App Link.
- Token from URL → "New password" screen.
- User enters password twice (or once with "show" button).
- PATCH/POST to server with token + new password.
- Success → auto login (get access/refresh tokens) → main screen.
Deep link handling in app
If app not installed — link should open web version (App Clip or just web form). Configured via Associated Domains + apple-app-site-association (iOS) and App Links + assetlinks.json (Android).
In SwiftUI + AppCoordinator:
// SceneDelegate or App with @main
.onOpenURL { url in
guard let token = url.queryParameters["token"] else { return }
coordinator.navigate(to: .resetPassword(token: token))
}
Pass token to Reset screen ViewModel, don't keep in URL or nav stack longer needed.
New password screen
SecureField with "show/hide" button — standard. textContentType(.newPassword) on iOS suggests Keychain password generator. Helpful — let user take generated password rather than "qwerty123".
Password strength indicator — colored bar with real-time calculation. Use zxcvbn (has Swift and Kotlin ports) — more honest assessment than "has digit + letter + symbol".
After successful change — invalidate all active sessions (server task, but mobile app should accept new tokens and remove old from Keychain).
SMS-recovery alternative
OTP on phone instead of email link. Pros: don't wait for email, don't depend on spam filters. Cons: SIM swap attack — attacker re-issues number and intercepts OTP. For high-sensitivity apps SMS recovery without extra factor insufficient.
Timeframe
Full password recovery flow (email form, deep link handling, new password screen, auto-login) — 4–7 business days per platform. Setup Universal/App Links + Apple App Site Association if not done yet — plus 1–2 days.







