almasumdev/awesome-mobile-security-agent-skills

mfa-on-mobile

Multi-factor authentication on mobile — TOTP, push-based MFA, and recovery UX.

Ver código fuente
Documento original del Skill

Contenido del repositorio de origen con títulos, ejemplos, código, tablas, enlaces e imágenes preservados.

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

FactorStrengthNotes
SMS OTPWeakSIM swap, SS7. Avoid unless regulation forces it.
Email OTPWeak–mediumInherits email account security.
TOTP (RFC 6238)MediumNo phishing resistance on its own.
Push approvalMediumGood UX; vulnerable to MFA fatigue.
FIDO2 / passkeysStrongPhishing-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.
kotlin
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:

  1. Server sends a push with a challenge_idnot an "approve / deny" payload alone.
  2. App fetches the challenge detail (amount, merchant, IP, location) over an authenticated channel.
  3. User reviews human-readable context and confirms.
  4. App signs challenge_id || context_hash with a biometric-gated Keystore key.
  5. 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 / amr claims in the id_token so 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 + ASAuthorizationPlatformPublicKeyCredentialProvider for passkeys.
  • Android: CredentialManager for passkeys / saved passwords.
  • Flutter: credential_manager package.
  • 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.
del mismo repositorio

Más Skills

Todos los Skills