Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Flauth 🔐

Flauth Logo

Flauth is a privacy-first, fully open-source TOTP authenticator. It offers both a GUI app (Android, macOS, Windows, Linux) and a lightweight CLI for viewing tokens directly in your terminal.

Download Latest Release | F-Droid | GitHub


🌟 Why Flauth?

  • 100% Open Source: Transparent and trustable code. Your secrets never leave your device unless you choose to sync them.
  • Flexible Backups:
    • Security Logic: Detailed backup and restore mechanisms.
    • Local Backup: Export/Import accounts as standard text files using system file pickers.
    • WebDAV Sync: Seamlessly sync your data with your private cloud (Nextcloud, Nutstore, etc.).
  • Privacy & Security:
    • Security Architecture: Detailed security implementation.
    • Encrypted Storage: Secrets are encrypted and stored in the device’s secure element (Keychain on iOS/macOS, Keystore on Android).
  • Modern UI: Focused on simplicity. Built with Material 3, supporting adaptive light and dark modes.

📸 Screenshots

Account List Backup & Sync Security Settings

⬇️ Download

You can download Flauth from the following sources:

  • F-Droid: The privacy-respecting FOSS Android app store.
  • GitHub Releases: Pre-compiled binaries for all supported platforms (Android APK, macOS, Linux, and Windows).

⌨️ CLI

For a lightweight experience, Flauth also provides a command-line tool to view TOTP tokens directly in your terminal — no GUI needed.

Pre-compiled binaries for Linux, macOS, and Windows are available on the GitHub Releases page.

Quick Install

curl -fsSL https://jiacai2050.github.io/flauth/install.sh | sh

For users in China:

curl -fsSL https://jiacai2050.github.io/flauth/install.sh | sh -s -- --china

Run install.sh --help for more options (e.g. --version, --prefix).

Usage

# Set the backup file path
export FLAUTH_BACKUP_FILE=/path/to/backup.flauth

# Show all tokens
flauth-cli

# Filter by keyword
flauth-cli github

# Show help
flauth-cli --help

🛡️ Permissions

  • Camera: To scan QR codes for adding accounts.
  • Local Storage/Network: To backup/restore accounts locally or via WebDAV.

📄 License

This project is licensed under the MIT License.

Backup & Restore Logic

This document describes the implementation details of Flauth’s backup and restore system, covering local file exports and WebDAV cloud synchronization.

1. Overview

Flauth supports two backup methods:

  • Local File: Export accounts to a file on your device or import from an existing file.
  • WebDAV Sync: Synchronize your accounts with a private cloud (e.g., Nextcloud, Nutstore) using the WebDAV protocol.

Both methods share the same underlying security architecture.

2. Security Architecture

To ensure the safety of your 2FA secrets, Flauth provides industry-standard encryption for backup files.

2.1 Encryption Standard

  • Algorithm: AES-256-CBC (Advanced Encryption Standard).
  • Key Derivation: PBKDF2 (Password-Based Key Derivation Function 2) with HMAC-SHA256.
  • Iterations: 10,000 rounds (balances performance and security).
  • Salting: A unique 16-byte random salt is generated for every backup to prevent rainbow table attacks.
  • IV: A 16-byte random Initialization Vector is used for every encryption to ensure uniqueness.

2.2 File Formats

Flauth unifies all backup files with the .flauth extension. The app automatically detects whether the file is encrypted or plain text during the import process.

Encrypted Format

Encrypted backups are stored as a JSON container:

{
  "version": 1,
  "kdf": {
    "algorithm": "pbkdf2",
    "iterations": 10000,
    "salt": "<Base64 encoded salt>"
  },
  "encryption": {
    "algorithm": "aes-256-cbc",
    "iv": "<Base64 encoded IV>",
    "data": "<Base64 encoded ciphertext>"
  }
}

Plain Text Format

If the user chooses to skip encryption, accounts are exported as a simple list of otpauth:// URIs, one per line (still saved with the .flauth extension).

3. Workflows

3.1 Export Workflow

  1. Collect Data: Gather all accounts and convert them to otpauth:// URIs.
  2. Security Choice: Prompt the user to enter a password (minimum 6 characters) or skip encryption.
  3. Encryption: If a password is provided, derive a 256-bit key and encrypt the content.
  4. Save/Upload:
    • Local: Use the system file picker to save the .flauth file (encrypted or plain text).
    • WebDAV: Upload the content to the configured remote path (defaults to backup-otpauth.flauth).

3.2 Import Workflow

  1. Read Content: Load the file string from local storage or download from WebDAV.
  2. Detection: Automatically check if the content is a JSON container with the expected encryption keys.
  3. Decryption:
    • If encrypted, prompt the user for the password.
    • Re-derive the key using the salt and iterations stored in the JSON.
    • Perform AES decryption.
  4. Parsing: Parse the resulting URI list and add new accounts to the local secure storage (skipping duplicates).

4. Platform Specifics (macOS)

For macOS users running the app in a development environment without official code signing, Flauth handles entitlements carefully to ensure the file picker functions correctly within the App Sandbox.

Flauth Authentication Architecture

This document details the security implementation mechanisms of Flauth, including PIN protection, biometric integration, and interaction logic.

1. Core Security Strategy: Two-Tier Protection

Flauth employs a Application-Level Independent Authentication combined with System-Level Biometrics.

  • Tier 1 (Biometrics): Uses the local_auth plugin to invoke iOS (FaceID/TouchID) or Android (Fingerprint/Face).
    • Android Implementation: The host Activity extends FlutterFragmentActivity and applies the Theme.MaterialComponents theme to ensure perfect compatibility with the system-level BiometricPrompt.
  • Tier 2 (Custom PIN): A 4-digit numeric password maintained by the application itself. This is the core fallback mechanism, establishing an independent defense boundary.

2. Storage Design (Storage Service)

All sensitive information is stored in flutter_secure_storage (using encrypted Shared Preferences/Keystore on Android and Keychain on iOS):

  • auth_pin: Stores the user-set PIN.
  • auth_biometric_enabled: Boolean, marks whether the user has authorized biometric use.
  • auth_failed_attempts: Number of consecutive incorrect entries.
  • auth_lockout_end: ISO8601 timestamp for when the lockout ends.
  • auth_pin_skipped: Marks whether the user chose to skip the initial setup.

3. Authentication Flow

3.1 Startup & Lifecycle Management

  1. Initialization: AuthProvider checks the existence of auth_pin and the lockout status.
  2. Lock Check: If the current time is earlier than auth_lockout_end, the UI disables input and shows a countdown.
  3. Auto-Auth: If not locked and biometrics are enabled, AuthScreen automatically pops up the verification dialog after the first frame is rendered.
  4. Background Auto-Lock:
    • When the app enters the background, the current timestamp is recorded.
    • When the app returns to the foreground, it checks the duration of absence. If the absence exceeds the 30-second Grace Period, the app forces a switch back to the unauthorized state, requiring re-authentication.

3.2 Verification Path & Anti-Brute Force

graph TD
    A[Enter AuthScreen] --> L{Check Lock Status?}
    L -- Locked --> M[Show Countdown/Disable Input]
    M --> |Countdown Ends| L
    L -- Not Locked --> B{Biometrics Enabled?}
    B -- Yes --> C[Show FaceID/Fingerprint]
    C -- Success --> D[Unlock to HomeScreen]
    C -- Failure/Cancel --> E[Wait for Manual PIN]
    B -- No --> E
    E --> F{PIN Matches?}
    F -- Yes --> D
    F -- No --> G[Fail Count +1]
    G --> H{Fail >= 5?}
    H -- Yes --> I[Set 30s Lockout]
    I --> L
    H -- No --> J[Show Remaining/Vibrate]
    J --> E

4. Platform Compatibility

  • Android:
    • Minimum Supported Version: Android 9.0 (SDK 28).
    • Build Config: Uses Java 11 and modern Kotlin compiler configuration.
    • Theming: Uses Material Components theme architecture (LaunchTheme and NormalTheme both extend Theme.MaterialComponents) to ensure consistent and stable fingerprint dialog styles across various device brands.
  • iOS:
    • Uses standard FaceID/TouchID authentication.
  • Desktop:
    • Currently only supports PIN authentication.

5. Security Features

  • Isolation: Does not reuse the phone’s lock screen password. Even if the phone password is compromised, the 2FA tokens remain secure.
  • Anti-Brute Force: 5 consecutive incorrect entries force a 30-second lockout. The lockout state is persisted and cannot be reset by restarting the app.
  • Leak Prevention: AuthScreen acts as an overlay; TOTP secrets are not decrypted in memory until verification passes.
  • Lifecycle Awareness: Uses WidgetsBindingObserver to monitor app state in real-time, preventing content from being viewed when the app is in the background.

6. Design Trade-offs

We chose a “Custom PIN” over “Reusing System Password” to address the risk of “Phone being snatched/borrowed while unlocked”. Although this increases the memory burden on the user, for an authenticator app managing account access rights, security is the primary priority. At the same time, the introduction of the 30-second background grace period balances security with the usability of frequent app switching.

Importing from Aegis Authenticator

Aegis is a popular open-source 2FA manager for Android. Migrating your accounts from Aegis to Flauth is simple and efficient.

This method allows you to migrate all accounts at once using Flauth’s local import feature.

Step 1: Export from Aegis

  1. Open Aegis on your Android device.
  2. Tap the Settings (gear icon) or the three-dot menu.
  3. Go to Import / Export.
  4. Select Export.
  5. Choose Plain-text JSON or Plain-text URI list.
    • Note: Flauth prefers the URI list for direct compatibility.
  6. Tap Export to file and save it to your device.

Step 2: Prepare the file

Flauth recognizes files with the .flauth extension.

  1. Locate the file you just exported (usually named aegis-export-....txt or .json).
  2. Rename the file extension to .flauth. For example: otpauth-backup.flauth.

Step 3: Import into Flauth

  1. Open Flauth.
  2. Go to Backup & Restore from the home screen menu.
  3. Switch to the Local File tab.
  4. Tap Import from File.
  5. Select your .flauth file.
  6. Flauth will display a message confirming how many new accounts were imported.

Alternative Method: QR Code (One-by-one)

If you only have a few accounts, you can scan them individually:

  1. In Aegis, long-press an account and select Show QR code.
  2. In Flauth, tap the [+] button on the home screen.
  3. Select Scan QR Code and scan the screen.

⚠️ Security Note

After a successful import, please immediately and securely delete the plain-text export file from Aegis, as it contains your unencrypted 2FA secrets.

Android Signing Guide

This document describes how to configure Android app signing for Flauth, both for local development and automated CI/CD using GitHub Actions.

1. Local Development Setup

To build a signed release APK locally, follow these steps:

Step 1: Create a Keystore

If you don’t have one, generate a keystore file:

keytool -genkey -v -keystore upload-keystore.jks -keyalg RSA -keysize 2048 -validity 10000 -alias upload

Step 2: Configure key.properties

Create a file at android/key.properties (this file is ignored by Git):

storePassword=your_keystore_password
keyPassword=your_key_password
keyAlias=upload
storeFile=upload-keystore.jks

Step 3: Build

Run the release build command:

flutter build apk --release

The build system will automatically detect key.properties and use your JKS file. If the file is missing, it will fallback to debug signing.

3. Verifying the Signature

After building the APK, you can verify if it was signed correctly using the apksigner tool (part of the Android SDK Build Tools).

On macOS, it’s typically located at: ~/Library/Android/sdk/build-tools/<version>/apksigner

Example command:

~/Library/Android/sdk/build-tools/34.0.0/apksigner verify --print-certs --verbose build/app/outputs/flutter-apk/app-release.apk

Check the output for the Signer #1 certificate DN and SHA-256 digest to ensure they match your keystore.


4. F-Droid & Third-party Builds

Our android/app/build.gradle.kts is designed to be environment-agnostic:

  • If signing keys are present, it produces a signed release.
  • If keys are missing (like on F-Droid build servers), it falls back to debug signing automatically. This ensures the source code remains buildable by anyone without needing private keys.

Performance Design inside Flauth

Flauth is designed to be a high-performance, battery-efficient TOTP authenticator. This document explains the key architectural decisions made to ensure smooth UI interaction even with a high-frequency (100ms) global heartbeat.

1. Global Heartbeat with Granular Updates

The application uses a central AccountProvider that maintains a Timer.periodic running every 100ms.

  • Why 100ms? This provides a 10Hz refresh rate, which is the “sweet spot” for LinearProgressIndicator. It ensures the progress bar moves smoothly across the 30-second TOTP window without looking jittery.
  • Why Persistent? The timer runs continuously regardless of the account list size. This simplifies the state machine and ensures that the UI is always ready to display the correct progress as soon as an account is added or revealed.

2. Rebuild Optimization (context.select)

The most critical optimization is how individual AccountTile widgets consume data.

The Problem

If every AccountTile used Provider.of<AccountProvider>(context), every single tile would rebuild 10 times per second because the provider notifies listeners every 100ms to update the top progress bar.

The Solution: Selector Pattern

We use context.select<AccountProvider, int>((p) => p.remainingSeconds) inside AccountTile.

  • Filtering Notifications: When notifyListeners() is called, select executes the selector function and compares the returned int with the previous value.
  • Lazy Rebuilding: Since remainingSeconds only changes once every 1000ms, the AccountTile widget ignores 9 out of 10 notifications.
  • Result: Even with 100+ accounts, the UI thread remains idle most of the time, only updating the specific tiles once per second.

3. Efficient TOTP Generation

TOTP codes are generated using the otp library, which performs HMAC-SHA1 calculations.

  • On-Demand Calculation: Codes are not pre-calculated or stored in the provider’s state. Instead, they are calculated during the build phase of the AccountTile.
  • Performance: HMAC-SHA1 is a lightweight cryptographic operation. Modern mobile CPUs can perform thousands of these per second, making it perfectly safe to calculate them during a widget’s 1fps rebuild.

4. Decoupled Services

  • StorageService: Uses flutter_secure_storage which offloads sensitive data handling to the OS (Keychain/Keystore). This is an asynchronous operation that doesn’t block the UI thread.
  • WebDavService: All network I/O and path normalization logic are encapsulated in a static service. This keeps the AccountProvider clean and focused solely on state management.

5. Summary of UI Refresh Rates

ComponentRefresh FrequencyStrategy
Global Timer100ms (10Hz)Timer.periodic
Progress Bar100ms (10Hz)Direct consumption in HomeScreen
Account Tile1000ms (1Hz)context.select optimization
WebDAV SyncOn DemandManual trigger

By combining a high-frequency global heartbeat with low-frequency local consumption, Flauth achieves a “silky smooth” feel with minimal battery impact.

TOTP URI Generator

This tool allows you to generate a standard otpauth:// URI and QR code for your 2FA accounts manually. This is useful if you have a plain secret key and want to import it into Flauth (or other authenticators) via QR code.

⚠️ Security Note This generator runs entirely in your browser. No data is sent to any server. However, please ensure you are in a safe environment when handling secret keys.

Generated URI:

Fill in the fields above...

ℹ️ How to Import into Flauth If you have multiple accounts to add, you can collect these URIs into a plain text file (one per line), save it with a .flauth extension, and use the Local File import feature in Flauth.


中文使用说明

  1. 在上方输入框填写 Issuer (如 GitHub), Account (如 user@mail.com) 和 Secret (密钥)。
  2. 页面会自动生成二维码和 otpauth:// 链接。
  3. 你可以直接用手机扫描二维码,或者:
    • 将生成的链接复制并保存到文本文件中(每行一个链接)。
    • 将该文件命名为 backup.flauth
    • 在 Flauth 的 Backup & Restore -> Local File 页面选择该文件进行导入。