Guardo

Powerful Flutter biometric authentication with automatic lock screen

Pub Version License: MIT Flutter

Seamlessly add biometric authentication to your Flutter apps with automatic lockout handling, customizable lock screens, and smart fallback to device credentials.


Table of Contents


Key Features

Smart Authentication

  • Biometric authentication - Support for Face ID, Touch ID, Fingerprint, and Iris scanning
  • Automatic fallback - Seamlessly switches to PIN/Pattern/Password when biometrics fail or are locked out
  • Smart detection - Automatically bypasses authentication UI when no auth methods are configured on device
  • Lockout handling - Intelligent handling of temporary and permanent biometric lockouts with user-friendly messages

Auto-Lock & Security

  • Auto-lock timer - Automatically locks app after configurable period of inactivity
  • App lifecycle management - Locks when app goes to background, unlocks on return with authentication
  • Manual lock control - Programmatically lock/unlock app based on your security requirements
  • Session persistence - Maintains authentication state across app launches with sticky authentication

Customizable UI

  • Custom lock screens - Build completely custom lock screens or use the provided default design
  • Theme support - Automatically adapts to system light/dark theme settings
  • Localization - Built-in support for English, Spanish, and Arabic with easy custom language addition
  • RTL support - Full right-to-left language support with automatic UI mirroring

Developer Experience

  • Simple API - Single widget wrapper for entire app authentication
  • Clean namespace - All methods organized under context.guardo.* for better code organization
  • Flexible control - Enable/disable authentication dynamically based on user preferences or app state
  • Debug mode - Easily disable authentication during development with a single flag

Installation

dependencies:
  guardo: ^1.0.0

Platform Setup

Android

Add to AndroidManifest.xml:

<uses-permission android:name="android.permission.USE_BIOMETRIC" />

Update your MainActivity to use FlutterFragmentActivity:

import io.flutter.embedding.android.FlutterFragmentActivity

class MainActivity: FlutterFragmentActivity() {
    // ...
}
iOS

Add to Info.plist:

<key>NSFaceIDUsageDescription</key>
<string>This app uses Face ID for secure authentication</string>

Quick Start

Wrap your app with Guardo - that's it!

import 'package:flutter/material.dart';
import 'package:guardo/guardo.dart';

void main() => runApp(
  Guardo(
    child: MaterialApp(
      home: MyHomePage(),
    ),
  ),
);

Usage

Basic Configuration

Guardo(
  enabled: true, // Enable/disable authentication
  config: GuardoConfig(
    localizedReason: 'Please authenticate to access the app',
    biometricOnly: true,
    lockTimeout: Duration(minutes: 5), // Auto-lock after inactivity
  ),
  child: YourApp(),
)

Unified API

All Guardo methods are organized under context.guardo.*:

// Check authentication status
if (context.guardo.isAuthenticated) {
  // User is authenticated
}

// Perform secure action
await context.guardo.action(
  onSuccess: () => deleteAccount(),
  onFailure: (error) => showError(error),
  reason: 'Authenticate to delete account',
);

// Manual lock/unlock
await context.guardo.lockApp();
await context.guardo.unlockApp();

// Check device capabilities
final hasAuth = await context.guardo.hasAuthenticationMethods();

Custom Lock Screen

Guardo(
  lockScreen: (context, onUnlock) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Icon(Icons.lock, size: 100),
            Text('App Locked'),
            ElevatedButton(
              onPressed: onUnlock,
              child: Text('Unlock'),
            ),
          ],
        ),
      ),
    );
  },
  child: YourApp(),
)

Actions

Actions are secure operations that require authentication before execution. The unified action() method intelligently handles both synchronous and asynchronous operations, automatically prompting for biometric authentication when needed.

How Actions Work

  • Authentication first - Prompts user for biometric/PIN authentication before executing
  • Automatic type detection - Detects if your operation is sync or async automatically
  • Error handling - Built-in failure callbacks for graceful error management
  • Return values - Supports operations that return values with type safety
// Synchronous action - blocks until completion
await context.guardo.action(
  onSuccess: () => performAction(),
  reason: 'Please authenticate',
);

// Asynchronous action - handles async operations seamlessly
await context.guardo.action(
  onSuccess: () async => await uploadData(),
  reason: 'Authenticate to upload',
);

// Action with return value - get results from secure operations
final result = await context.guardo.action<String>(
  onSuccess: () async => await fetchSecretKey(),
  onFailure: (error) => 'default_key',
  reason: 'Access encryption key',
);

Deprecated Methods

These methods are still available for backward compatibility but will be removed in a future version. Use the new context.guardo.* API instead.

Deprecated Method New Method
context.lockApp() context.guardo.lockApp()
context.unlockApp() context.guardo.unlockApp()
context.resetLockTimer() context.guardo.resetLockTimer()
context.isAuthenticated context.guardo.isAuthenticated
context.isAppLocked context.guardo.isAppLocked
context.isGuardoEnabled() context.guardo.isEnabled()
context.guardoState context.guardo.state
context.secureAction() context.guardo.action()
context.guardoActionWithResult<T>() context.guardo.action<T>()
context.guardoAsyncAction() context.guardo.action() with async
context.guardoAsyncActionWithResult<T>() context.guardo.action<T>() with async

Localization

Built-in Languages

  • English (en)
  • Spanish (es)
  • Arabic (ar)

Setup

MaterialApp(
  localizationsDelegates: const [
    GuardoLocalizations.delegate,
    GlobalMaterialLocalizations.delegate,
    GlobalWidgetsLocalizations.delegate,
  ],
  supportedLocales: const [
    Locale('en'), Locale('es'), Locale('ar'),
  ],
  home: Guardo(child: MyApp()),
)

Custom Languages

Create a custom localization:

class GuardoLocalizationsKo extends GuardoLocalizations {
  @override
  String get authenticateToUnlock => '잠금을 해제하려면 인증해 주세요';
  // ... implement other required strings
}

Error Handling

try {
  await context.guardo.action(
    onSuccess: () => sensitiveOperation(),
  );
} on BiometricLockoutException {
  // Handle temporary lockout
  showMessage('Too many attempts. Try again later.');
} on BiometricUnavailableException {
  // Handle unavailable biometrics
  showMessage('Biometrics not available');
}

Common Use Cases

Banking App

// Secure transaction
await context.guardo.action(
  onSuccess: () async => await transferMoney(amount),
  reason: 'Authenticate to transfer funds',
);

Note-Taking App

// Lock on app background
Guardo(
  config: GuardoConfig(
    lockTimeout: Duration(seconds: 30),
  ),
  child: NotesApp(),
)

Healthcare App

// View sensitive data
final medicalRecords = await context.guardo.action<List<Record>>(
  onSuccess: () async => await fetchMedicalRecords(),
  onFailure: (e) => [],
  reason: 'Authenticate to view medical records',
);

API Reference

GuardoConfig

Property Type Default Description
localizedReason String 'Please authenticate...' Auth prompt message
biometricOnly bool true Use only biometrics
lockTimeout Duration? null Auto-lock timeout
autoCheckOnStart bool true Check auth on start

Context Extensions

All methods available via context.guardo.*:

Method Description
action<T>() Execute authenticated action
lockApp() Lock the app manually
unlockApp() Unlock with authentication
resetLockTimer() Reset auto-lock timer
isAuthenticated Check if authenticated
isEnabled() Check if Guardo is enabled
hasAuthenticationMethods() Check if auth methods available

Troubleshooting

App not locking?

Ensure Guardo wraps your entire MaterialApp:

Guardo(
  config: GuardoConfig(lockTimeout: Duration(minutes: 5)),
  child: MaterialApp(...), // Correct
)

Biometrics not working?

Check device capabilities first:

if (await context.guardo.hasAuthenticationMethods()) {
  // Safe to use authentication
}

Debug mode?

Disable authentication during development:

Guardo(
  enabled: !kDebugMode, // Disabled in debug mode
  child: YourApp(),
)

Platform Support

Platform Biometric Types Requirements
iOS Face ID, Touch ID iOS 9.0+
Android Fingerprint, Face, Iris API 23+

Contributing

We welcome contributions! See our Contributing Guidelines for details.

# Clone the repository
git clone https://github.com/fathialamre/guardo.git

# Run example app
cd example
flutter run

License

MIT License - see the LICENSE file for details.


Made with love for the Flutter community

Star on GitHubReport BugRequest Feature

Libraries

guardo