# OTP Screen Displays the current TOTP (Time-based One-Time Password) code for each enrolled bank authenticator. Used when confirming transfers, QR payments, or other 2FA-protected operations. --- ## Fragment — `OtpFragment` Hosts one card per enrolled bank authenticator. Banks with no stored TOTP seed are not shown. --- ## TOTP Display Each card shows: - Bank logo, bank name and account holder name - A circular countdown ring with the seconds left in the current 30-second window; the ring and code turn red in the last 5 seconds - The current 6-digit TOTP code (large text) with a copy button - The next window's code (smaller, below a divider) with its own copy button — handy when the current code is about to expire - The codes refresh automatically when the window expires — no user interaction needed Tapping anywhere on the card also copies the current code. If no logins have a seed, an empty-state message is shown instead. --- ## Seed Actions Long-pressing a card opens a menu with: ### Export seed A dialog titled `{bank} · {name}` showing: - A QR code of a minimal `otpauth://totp/{BANK}?secret=…` link (e.g. `otpauth://totp/BML?secret=…`), always drawn black-on-white so it scans in dark mode. No username or issuer is included, and algorithm, digits and period are left out because SHA1, 6 and 30s are the spec defaults. Export is single-account only; `otpauth-migration://` is supported for import but never produced. - The Base32 seed in groups of 4 (selectable text) - A **Copy seed** button. The copy is flagged `EXTRA_IS_SENSITIVE`, so Android 13+ hides the value in the clipboard preview. ### Update seed Replaces the stored seed for that login, e.g. after re-enrolling the authenticator with the bank. - A red warning banner explains that the old seed is deleted permanently. - The new seed can be typed or pasted (raw Base32 or an `otpauth://` link) or scanned with the QR button. Scans that contain several accounts (`otpauth-migration://`) ask which one to use. - Once the input is a valid seed, a live preview shows its current and next code with a countdown so the user can check it against the bank before saving. The preview is the same card as the sign-in screen (`view_otp_preview.xml`, shared by both), and tapping it copies the code. Input that isn't valid Base32, is shorter than 8 characters (such as a pasted 6-digit code), or matches the current seed disables **Replace**. - **Replace** asks for confirmation ("Delete old seed?"). Confirming calls `CredentialStore.updateMibOtpSeed()` / `updateBmlOtpSeed()`, which overwrite only the encrypted seed. For MIB it also calls `MibLoginFlow.updateOtpSeed()` so silent re-login uses the new seed. The username, password and sessions are not touched. Other places that need an OTP (transfers, QR pay, pay with card) read the seed from `CredentialStore` each time, so they pick up the new seed immediately. ### Algorithm Standard RFC 6238 TOTP: - Hash: SHA-1 - Window: 30 seconds - Digits: 6 - Seed: stored per-bank in `CredentialStore` (encrypted) --- ## Supported Banks One card is rendered for every MIB and every BML login that has a stored OTP seed (`OtpFragment.kt`), sorted by the user's [login order](00-app-overview.md#login-order). Seeds are per-`loginId` in `CredentialStore`. | Bank | Seed source | Card title / subtitle | |---|---|---| | MIB | `loadMibCredentials(loginId).otpSeed` (entered at login) | `MIB` / `{fullName}` | | BML | `loadBmlCredentials(loginId).otpSeed` (entered at login) | `BML` / `{fullName}` | If no full name has been cached the subtitle falls back to `"Authenticator"` and a background `MibProfileClient.fetchPersonalProfile()` / `BmlAccountClient.fetchUserInfo()` call refreshes it. --- ## Background Name Refresh When the screen opens, the fragment may fire a background API call to refresh the account holder name associated with each seed. This is a best-effort call — failure does not affect OTP display. --- ## Usage The OTP screen is informational — the user copies the displayed code manually and enters it wherever required (e.g., in `TransferFragment`'s OTP dialog, or in an external portal). The code is never submitted automatically from this screen. --- ## Security The TOTP seeds are stored encrypted in `CredentialStore`. They are never logged or included in error reports. They leave the app only when the user chooses **Export seed**. ---   --- [← Activities](09-activities.md)     **Next →** [PayMV QR Screen](11-paymv-qr-screen.md)