How to use
- Copy the installation command and review the source package before installing it in your own agent environment.
- Check the source document for required tools, credentials and supported hosts.
- Describe your input and desired deliverable; review the output against the source material.
npx skills add https://github.com/almasumdev/awesome-mobile-security-agent-skills --skill mfa-on-mobileBefore you start
- Installation does not include a model subscription, API allowance or permission to access your files.
- Repository stars and installation counts describe activity, not an independent quality or security test.
Rendered from the source repository. Headings, examples, code, tables, links, and referenced images are preserved.
MFA on Mobile
Instructions
MFA on mobile covers both the app as the authenticator (TOTP / push) and the app as the user (consuming a second factor during login).
1. Factor Types
| Factor | Strength | Notes |
|---|---|---|
| SMS OTP | Weak | SIM swap, SS7. Avoid unless regulation forces it. |
| Email OTP | Weak–medium | Inherits email account security. |
| TOTP (RFC 6238) | Medium | No phishing resistance on its own. |
| Push approval | Medium | Good UX; vulnerable to MFA fatigue. |
| FIDO2 / passkeys | Strong | Phishing-resistant. Prefer where available. |
2. TOTP as an Authenticator App
- Use the standard RFC 6238 with SHA-1 or SHA-256, 6 digits, 30-second period for maximum compatibility. Document any deviation.
- Store the shared secret only in Keystore / Keychain, wrapped by a biometric-gated key.
- Never back up TOTP secrets to iCloud / Google Drive in plaintext.
fun generateTotp(secret: ByteArray, time: Long = System.currentTimeMillis()): String {
val counter = ByteBuffer.allocate(8).putLong(time / 1000 / 30).array()
val mac = Mac.getInstance("HmacSHA1").apply { init(SecretKeySpec(secret, "HmacSHA1")) }
val hash = mac.doFinal(counter)
val offset = hash.last().toInt() and 0x0f
val bin = ((hash[offset].toInt() and 0x7f) shl 24) or
((hash[offset + 1].toInt() and 0xff) shl 16) or
((hash[offset + 2].toInt() and 0xff) shl 8) or
(hash[offset + 3].toInt() and 0xff)
return "%06d".format(bin % 1_000_000)
}3. Push-Based MFA (Done Right)
Push MFA is a signing operation, not a boolean tap:
- Server sends a push with a
challenge_id— not an "approve / deny" payload alone. - App fetches the challenge detail (amount, merchant, IP, location) over an authenticated channel.
- User reviews human-readable context and confirms.
- App signs
challenge_id || context_hashwith a biometric-gated Keystore key. - Server verifies the signature against the registered device public key.
Never auto-approve. Never accept a push whose contents you didn't fetch over HTTPS from the server.
4. Preventing MFA Fatigue
- Require number matching (user types a 2-digit code shown on the origin device).
- Throttle push requests server-side; after N rapid prompts, fall back to a stronger factor.
- Log and surface unusual prompts (new country, new device) in an in-app audit log.
5. Consuming MFA During Login
If your app is an OAuth client:
- Prefer
acr_values/amrclaims in theid_tokenso the server tells you what factors were used. - Support the browser flow's step-up — do not re-implement the challenge in the native app.
- On step-up failure, clearly distinguish "wrong code" from "account locked".
6. Recovery UX
Recovery is where MFA projects usually fail:
- Provide backup codes at enrollment (one-time, downloadable, printable). Store the hash server-side.
- Support FIDO2 security keys as a non-lose-your-phone recovery option when feasible.
- Document an account-recovery flow that is slower and more verified than normal login (identity check, cooling-off period).
- Never allow "email a reset link" to fully bypass MFA on high-value accounts.
7. Platform APIs
- iOS:
ASAuthorizationController+ASAuthorizationPlatformPublicKeyCredentialProviderfor passkeys. - Android:
CredentialManagerfor passkeys / saved passwords. - Flutter:
credential_managerpackage. - React Native:
react-native-passkey.
Passkeys are strictly better than TOTP for most apps; ship them where the user base has device support.
Checklist
- [ ] SMS is not the only second factor offered on high-value accounts.
- [ ] TOTP secrets live in Keystore / Keychain, biometric-gated.
- [ ] Push MFA signs a server-provided challenge (not a boolean approval).
- [ ] Number matching or equivalent anti-fatigue control is in place.
- [ ] Backup codes and/or passkey recovery are offered at enrollment.
- [ ] Account recovery is explicitly slower / more verified than normal login.
- [ ] Passkeys are supported where the platform allows.


