Skip to main content
03Authentication

Better
Authenticator

by Yashesh Bharti
A TOTP authenticator built into an iOS keyboard extension. Tap a code and it inserts directly into the active text field. No app switching, no clipboard, no "Allow Full Access".
Status
Live
Platform
iOS
Language
Swift
01Problem

App-switch fatigue, and a worse problem

Every 2FA login pulls you out of context. Open the authenticator app, scroll to the right account, memorise six digits in thirty seconds, switch back, type, hit submit before the code expires. Now do that fifteen times a day. The cost is not security, the cost is friction.

The deeper problem is the clipboard. Most authenticator apps recommend long-press + copy as the "fast" path. The clipboard is shared with every app on the device, persists across launches, and is read freely by third-party keyboards and pasteboard-watching apps. A 2FA code in the clipboard is a 2FA code anyone can read.

02Product

2FA codes on your keyboard

Better Authenticator is a custom iOS keyboard. When you switch to it inside any app, your TOTP codes appear in a horizontal scroll above the QWERTY layout, each with a live countdown ring. One tap and the code is injected directly into the active text field through Apple's textDocumentProxy.insertText(). No clipboard, no copy, no paste, no app switch.

03What I built

Three components

Companion app (SwiftUI)
QR scanner via AVFoundation, account CRUD with reordering, manual entry, biometric gate that auto-locks when backgrounded.
Shared framework
RFC 6238 TOTPGenerator, Keychain manager with shared access group, Base32 decoder, Account model, BiometricAuthManager. Linked into both targets via App Group.
Keyboard extension
Custom UIInputViewController with a QWERTY layout and a horizontal auth bar. Tap-to-insert via textDocumentProxy. Countdown ring per code. No 'Allow Full Access' enabled.
04Architecture

App Group, not network

The keyboard extension cannot read the companion app's files. It cannot make network requests without "Allow Full Access". So how does it know your TOTP secrets? Through a shared Keychain access group, scoped by an App Group identifier.

The companion app writes secrets to the shared Keychain under kSecAttrAccessibleAfterFirstUnlock. The keyboard extension, signed with the same App Group entitlement, reads them back. Generating a TOTP code is pure local math (HMAC-SHA1 over the secret and the time counter), so the keyboard never touches the network. iOS' 50 MB memory limit for keyboard extensions is plenty.

05Technical stack

Stack

Language
Swift
Companion app
SwiftUI + AVFoundation (QR scan)
Keyboard ext
UIInputViewController
Shared layer
App Group + Shared Keychain
TOTP
RFC 6238, SHA1/256/512, 6/7/8 digit
Auth
FaceID / TouchID + passcode fallback
Sync (opt-in)
iCloud Keychain via kSecAttrSynchronizable
06Product decisions

Choices that matter

  • Refuse "Allow Full Access". Most third-party keyboards demand it. We do not. The whole architecture is designed so that the keyboard never needs network, GPS, camera, or anything that would justify the prompt. Users get the keyboard with the smallest possible attack surface.
  • Bypass the clipboard. textDocumentProxy.insertText() writes straight into the text field. The code never touches the pasteboard, never persists, and never leaks to other apps.
  • Biometric on the companion, not the keyboard. The keyboard cannot present a FaceID prompt mid-typing without breaking the flow. So the companion app is biometric-gated for setup, and the codes themselves are guarded by being usable only when iOS itself is unlocked (kSecAttrAccessibleAfterFirstUnlock).
  • iCloud Keychain sync is opt-in. Default is local-only. Users who want their codes on a second device flip a toggle, which sets kSecAttrSynchronizable on each secret. The default makes the strongest privacy choice for them.
07Security and privacy

Threat model

TOTP secrets live in the iOS Keychain with shared access group com.keyauth.shared, scoped to the App Group, accessible only after first device unlock. The keyboard extension has zero network entitlement. The companion app uses biometric unlock and auto-locks on background. Codes are inserted via insertText, so they never enter the pasteboard. iCloud Keychain sync, when enabled, inherits Apple's end-to-end encryption.

08Outcome

What ships today

Better Authenticator is live as an iOS keyboard. RFC 6238 compliant TOTP with SHA1, SHA-256, and SHA-512, 6-, 7-, and 8-digit codes, and 30-second or 60-second periods. Standard otpauth:// URI imports via QR scan or manual entry. The companion app is the management surface; the keyboard is the daily-use surface.

09Links

Read more

← All work notesBetter Authenticator / by Yashesh Bharti