MF

Guidance for integrating TOTP and push-based MFA on mobile apps, emphasizing security best practices.

Install

mkdir -p .claude/skills/mfa-on-mobile && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/10785" && unzip -o skill.zip -d .claude/skills/mfa-on-mobile && rm skill.zip

Installs to .claude/skills/mfa-on-mobile

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Multi-factor authentication on mobile — TOTP, push-based MFA, and recovery UX. Use when adding or reviewing a second factor.
124 chars✓ has a “when” trigger
Intermediate

Key capabilities

  • Implement TOTP generation
  • Add push-based MFA
  • Review MFA recovery flows

How it works

It provides patterns for TOTP and push-based MFA, emphasizing secure storage and anti-fatigue controls.

Inputs & outputs

You give it
Authentication factor requirements
You get back
MFA implementation strategy

When to use mfa-on-mobile

  • Implementing TOTP generation
  • Adding push-based MFA support
  • Reviewing MFA recovery flows

About this skill

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.
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.

When not to use it

  • SMS-only authentication
  • High-value account bypass

Prerequisites

Keystore/Keychain access

Limitations

  • SMS is weak and discouraged

How it compares

It mandates secure storage and challenge-based push MFA instead of simple boolean approvals.

Compared to similar skills

mfa-on-mobile side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
mfa-on-mobile (this skill)03moNo flagsIntermediate
security-owasp02moNo flagsIntermediate
security-checklist04moReviewIntermediate
android-mobile-hardening02moNo flagsIntermediate

Try saying

Example prompts that trigger this skill in your AI assistant.

Search skills

Search the agent skills registry