Login Failures: Common Causes and Fixes (2026)
Login is the entry point, and when it breaks, every user metric crashes with it. Login failures have asymmetric impact — one bug blocks all activity downstream. This guide covers the repeating root ca
Login is the entry point, and when it breaks, every user metric crashes with it. Login failures have asymmetric impact — one bug blocks all activity downstream. This guide covers the repeating root causes and how to fix them systematically.
Symptoms
- "Invalid credentials" on correct password
- Login succeeds but user lands back at login screen
- Token expires immediately
- Biometric works but password fallback does not
- OAuth redirect never returns to app
- OTP never arrives
Common causes
1. Token refresh race condition
Two API calls trigger simultaneous token refresh. Second refresh invalidates first. User session lost mid-action.
Fix: Singleton refresh with shared Promise. Only one active refresh at a time.
2. Incorrect bearer token format
Client sends Authorization: {token} instead of Authorization: Bearer {token}. Server rejects.
Fix: Interceptor that always formats correctly. Unit tests on auth headers.
3. Expired token not auto-refreshed
Token expires, client calls API, gets 401, does not refresh and retry. User sees generic error.
Fix: Interceptor catches 401 → refresh token → retry original request.
4. Refresh token missing scope
Refresh token issued without offline_access / required scope. Silent refresh fails on next use.
Fix: Backend issues refresh token with proper scopes. Client verifies.
5. OAuth redirect URI mismatch
App's redirect URI registered with provider does not exactly match what app sends. OAuth fails silently.
Fix: Register every variant (myapp://callback, myapp://callback/) that app might use.
6. Deep link swallowed by splash
OAuth redirect via deep link arrives during splash; intent consumed by splash activity, never passed to OAuth handler.
Fix: Splash inspects intent, passes along if matching OAuth pattern.
7. WebView cookies disabled
OAuth via WebView requires cookies for session; Android WKWebView default disables third-party cookies. OAuth fails.
Fix: Use Chrome Custom Tabs for OAuth, not WebView. Or enable cookies correctly.
8. Biometric key invalidated
User added new biometric (fingerprint, face). Keystore auto-invalidated key tied to biometric. Next unlock attempt fails.
Fix: Detect KeyPermanentlyInvalidatedException → fall back to password → re-enroll biometric key.
9. Password contains characters server rejects
Password with trailing space, accented characters, 100+ chars. Some servers silently strip or reject.
Fix: Server accepts full Unicode, up to 256+ chars, never silently trims. Test with edge characters.
10. OTP SMS not arriving
Wrong phone format (missing +country), carrier blocks SMS from your provider, user's spam filter.
Fix: Multiple SMS providers; fallback to email; clear "SMS not arriving?" help text.
11. Clock skew
TOTP (authenticator app) fails if device clock is >30 seconds off.
Fix: Server accepts ±30 seconds window. Client syncs with NTP.
12. Session fixation attack mitigation
Server regenerates session ID post-login. Client still has old. All requests rejected.
Fix: Client reads new session ID from login response. Don't reuse pre-login session.
Diagnosis
Server-side
- Check auth service logs for login attempts
- Check rate-limit counter (user being throttled?)
- Check account state (locked, suspended?)
Client-side
- Network inspector (Charles, Proxyman, mitmproxy) to see exact request / response
- Console logs around auth interceptor
- Crashlytics breadcrumbs if crash accompanies failure
End-to-end
- Reproduce with fresh install
- Reproduce with specific account (some users hit state bugs)
- Reproduce on specific OS version
Fix patterns
- Single source of truth for auth state. One auth manager, no scattered
isLoggedInchecks. - Interceptor handles all auth. Token refresh, retry, logout on consistent failure.
- Clear error messages. "Wrong password" vs "Account locked" vs "Server error" — user needs to know.
- Recovery flows always accessible. Forgot password, help link, contact support.
How SUSA catches login failures
SUSA's login phase detects login screens and drives them with provided credentials. Login verdict is first-class: SUCCESS / FAILED / STUCK, with repro steps. If login fails, exploration aborts with clear error classification (wrong creds vs server error vs stuck).
susatest-agent test myapp.apk --username test@example.com --password correct-horse
The adversarial persona probes login-adjacent surfaces: rapid re-attempts, invalid inputs, stress-testing the flow.
Login is high-stakes. Allocate disproportionate QA time to it; never ship a release where login regresses.
Test Your App Autonomously
Upload your APK or URL. SUSA explores like 10 real users — finds bugs, accessibility violations, and security issues. No scripts.
Try SUSA Free