A professional, enterprise-grade licensing and activation package for Flutter applications.
Supports Windows Β· macOS Β· Linux Β· Android Β· iOS Β· Web.
---
| Feature | Description |
|---|---|
| π License Keys | XXXX-XXXX-XXXX-XXXX format with auto-format & validation |
| π Online Validation | JWT-signed server validation with retry + back-off |
| π΄ Offline Mode | Configurable grace period (default 7 days) |
| π₯οΈ Device Binding | Per-platform hardware fingerprint |
| π AES-256-GCM | Triple-layer local storage encryption |
| βοΈ RSA-2048 | Server signature verification on every license token |
| β±οΈ Clock Tamper | Server-time + last-known-time rollback detection |
| π‘οΈ Anti-Tamper | Root/jailbreak, emulator, debugger, storage integrity |
| π Trial Period | Per-device trial with optional server registration |
| π Feature Flags | Per-feature licensing (FeatureGuard widget) |
| π Subscriptions | Perpetual Β· Subscription Β· Trial Β· Educational Β· OEM |
| π Notifications | In-app expiry / grace / revoke alerts via listener |
| π¨ Custom UI | Light/dark themes, branding, RTL/LTR locale support |
| π± Ready UI | ActivationScreen, ExpiredScreen, TrialScreen, LicenseInfoScreen |
dependencies:
app_shield: ^1.0.0import 'package:flutter/material.dart';
import 'package:app_shield/app_shield.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await AppShield.initialize(
config: AppShieldConfig(
appId: 'com.mycompany.erp',
apiBaseUrl: 'https://license.mycompany.com/api',
apiKey: 'pk_live_your_api_key_here',
appSecret: 'strong-random-secret-for-local-encryption',
publicKey: '-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----',
enableTrial: true,
trialDays: 15,
enableOfflineMode: true,
offlineGraceDays: 7,
enableDeviceBinding: true,
maxDevicesPerLicense: 1,
enableClockCheck: true,
validationIntervalHr: 24,
theme: AppShieldTheme.light(
primaryColor: Colors.blue,
brandName: 'My ERP System',
),
),
);
runApp(const MyApp());
}class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: AppShieldGuard(
child: const HomePage(),
onLicenseInvalid: () => const ActivationScreen(),
onTrialExpired: () => const ExpiredScreen(),
),
);
}
}AppShieldGuard automatically:
- Checks license on startup
- Re-checks on every foreground resume
- Runs periodic background validation
- Listens to revocation / status push from server
FeatureGuard(
feature: AppShieldConstants.featureAdvancedReports,
child: const AdvancedReportsPage(),
fallback: const UpgradePromptWidget(), // optional
)// GoRouter
GoRoute(
path: '/reports',
redirect: (ctx, state) =>
RouteGuard.checkFeature('advanced_reports', '/upgrade'),
builder: (ctx, state) => const ReportsPage(),
)
// Navigator
Navigator.push(
context,
RouteGuard.protectedRoute(
feature: 'advanced_reports',
builder: (_) => const ReportsPage(),
),
);final shield = AppShield.instance;
// Check status
final status = await shield.checkLicense();
// Activate a key
final result = await shield.activate('ABCD-1234-EFGH-5678');
if (result.success) { /* navigate to app */ }
// Validate online
final resp = await shield.validateOnline();
// Restore license to new device
await shield.restore(licenseKey: 'ABCD-...', email: 'user@example.com');
// Start trial
await shield.startTrial();
// Check feature
if (shield.hasFeature(AppShieldConstants.featureCloudBackup)) { /* ... */ }
// Days remaining
print(shield.daysRemaining);
// Deactivate
await shield.deactivate();app_shield/
βββ lib/
β βββ app_shield.dart # Main entry point + exports
β βββ app_shield_config.dart # AppShieldConfig class
β βββ src/
β βββ core/
β β βββ license_manager.dart # Lifecycle engine
β β βββ device_fingerprint.dart # Per-platform fingerprinting
β β βββ encryption_service.dart # AES-256-GCM + RSA + HMAC
β β βββ api_client.dart # HTTP client with retry
β β βββ clock_verifier.dart # Anti-clock-tamper
β β βββ tamper_detector.dart # Root/debug/emulator checks
β βββ models/
β β βββ license_model.dart
β β βββ device_model.dart
β β βββ feature_model.dart
β β βββ activation_result.dart
β β βββ validation_response.dart
β β βββ activity_log_entry.dart
β β βββ tamper_record.dart
β βββ services/
β β βββ validation_service.dart # Online activate/validate/restore
β β βββ storage_service.dart # Triple-layer encrypted storage
β β βββ trial_service.dart # Trial lifecycle
β β βββ sync_service.dart # Telemetry + tamper reports
β β βββ notification_service.dart
β βββ guards/
β β βββ app_shield_guard.dart # Root widget gate
β β βββ feature_guard.dart # Per-feature widget gate
β β βββ route_guard.dart # Navigator/GoRouter helpers
β βββ ui/
β β βββ screens/
β β β βββ activation_screen.dart
β β β βββ trial_screen.dart
β β β βββ expired_screen.dart
β β β βββ license_info_screen.dart
β β β βββ offline_mode_screen.dart
β β β βββ tamper_detected_screen.dart
β β βββ widgets/
β β β βββ license_input.dart
β β β βββ status_card.dart
β β β βββ expiry_badge.dart
β β β βββ device_info_widget.dart
β β β βββ feature_list_widget.dart
β β βββ themes/
β β βββ app_shield_theme.dart
β β βββ app_shield_colors.dart
β βββ utils/
β βββ constants.dart
β βββ helpers.dart
β βββ logger.dart
β βββ exceptions.dart
βββ example/ # Complete demo app
βββ test/ # Unit tests
βββ pubspec.yaml
βββ README.md
βββ CHANGELOG.md
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Layer Technology Purpose β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£
β Local Storage AES-256-GCM Encrypt license data β
β Key Derivation PBKDF2-HMAC-SHA256 Derive AES key β
β Integrity HMAC-SHA-256 Detect tampering β
β Transport TLS 1.3 Secure API calls β
β Server Sig. RSA-2048 Verify license token β
β Sessions JWT Validate auth tokens β
β Clock Server NTP sync Anti-clock-rollback β
β Storage Layers Keychain + Prefs Redundant persistence β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Triple-layer storage prevents simple file deletion:
- FlutterSecureStorage (OS Keychain / Android Keystore) β primary
- SharedPreferences (encrypted blob) β fallback
- HMAC tag in secure storage β tamper detection
| Platform | Fingerprint Sources |
|---|---|
| Windows | Device ID (WMI), Computer Name, OS Version |
| macOS | Hardware UUID (IOKit), hostname, OS version |
| Linux | /etc/machine-id, hostname, CPU info |
| Android | ANDROID_ID, Build.MANUFACTURER, Build.MODEL |
| iOS | identifierForVendor, device model |
| Web | User-Agent, browser info, canvas entropy |
| Type | Description | Example Use Case |
|---|---|---|
perpetual |
One-time purchase, no expiry | Desktop software |
subscription |
Monthly / yearly recurring | SaaS apps |
trial |
Free evaluation period | Lead generation |
educational |
Discounted student license | Schools, universities |
enterprise |
Custom large-scale license | Large organizations |
oem |
Bundled / reseller license | White-label products |
AppShieldConfig(
// ββ Required ββββββββββββββββββββββββββββββββββββββββββββββββ
appId: 'com.myapp', // Unique app identifier
apiBaseUrl: 'https://license...', // License server URL
apiKey: 'pk_live_...', // API authentication key
// ββ Security ββββββββββββββββββββββββββββββββββββββββββββββββ
appSecret: 'strong-random-secret', // Local AES encryption key
publicKey: '-----BEGIN PUBLIC KEY-----...', // RSA-2048 verification
// ββ Offline βββββββββββββββββββββββββββββββββββββββββββββββββ
enableOfflineMode: true,
offlineGraceDays: 7, // Days allowed without server
// ββ Trial ββββββββββββββββββββββββββββββββββββββββββββββββββββ
enableTrial: true,
trialDays: 15, // Free trial length
// ββ Device βββββββββββββββββββββββββββββββββββββββββββββββββββ
enableDeviceBinding: true,
maxDevicesPerLicense: 1, // Devices per license key
// ββ Validation βββββββββββββββββββββββββββββββββββββββββββββββ
enableClockCheck: true, // Detect clock manipulation
validationIntervalHr: 24, // Hours between server checks
// ββ Tamper Detection βββββββββββββββββββββββββββββββββββββββββ
enableTamperDetection: true,
enableRootJailbreakCheck: true,
enableEmulatorCheck: false, // Enable in production
enableDebuggerCheck: false, // Enable in release builds
// ββ Subscription βββββββββββββββββββββββββββββββββββββββββββββ
enableAutoRenewal: false,
buyLicenseUrl: 'https://example.com/buy',
supportUrl: 'https://example.com/support',
// ββ UI βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
theme: AppShieldTheme.light(
primaryColor: Colors.blue,
brandName: 'My App',
logoAsset: 'assets/logo.png',
locale: 'en', // 'en', 'fr', 'ar'
),
// ββ Telemetry βββββββββββββββββββββββββββββββββββββββββββββββββ
enableTelemetry: false, // Opt-in usage analytics
// ββ Logging ββββββββββββββββββββββββββββββββββββββββββββββββββ
enableLogging: true,
)Your backend must implement these endpoints:
| Method | Path | Description |
|---|---|---|
POST |
/license/activate |
Activate a key on a device |
POST |
/license/validate |
Validate license + device |
POST |
/license/deactivate |
Remove device binding |
POST |
/license/restore |
Restore key to new device |
POST |
/license/renew |
Renew subscription |
GET |
/license/info |
Get license details |
GET |
/license/features |
Get available features |
POST |
/trial/start |
Register trial start |
POST |
/telemetry/send |
Receive usage events |
GET |
/updates/check |
Check for app updates |
GET |
/system/time |
Return server UTC time |
POST |
/auth/otp/send |
Send OTP email |
POST |
/auth/otp/verify |
Verify OTP code |
POST /license/activate
{
"license_key": "ABCD-1234-EFGH-5678",
"device": {
"fingerprint": "A1B2-C3D4-E5F6-0708",
"platform": "windows",
"hostname": "USER-PC",
"os_version": "Windows 11"
},
"app_id": "com.mycompany.erp",
"timestamp": 1713696000000
}{
"status": "success",
"data": {
"license": {
"key": "ABCD-1234-EFGH-5678",
"type": "subscription",
"plan": "professional",
"activated_at": "2026-04-21T10:30:00Z",
"expires_at": "2027-04-21T10:30:00Z",
"device_id": "A1B2-C3D4-E5F6-0708",
"features": {
"advanced_reports": true,
"multi_user": true,
"api_access": true,
"cloud_backup": false
},
"limits": {
"max_users": 10,
"max_records": 100000
},
"signature": "base64_rsa_signature_here"
},
"token": "eyJhbGciOiJIUzI1NiIs..."
}
}AppShield.instance.notificationService.addListener((notification) {
switch (notification.type) {
case AppShieldNotificationType.expiryWarning:
// Show banner: "License expiring in X days"
break;
case AppShieldNotificationType.licenseRevoked:
// Lock app immediately
break;
case AppShieldNotificationType.updateAvailable:
// Show update dialog
break;
default:
debugPrint(notification.message);
}
});flutter testTests cover:
Licensemodel (serialization, validity, feature checks)AppShieldHelpers(key formatting, date helpers)EncryptionService(encrypt/decrypt, HMAC, SHA-256)
| Code | Exception | Cause |
|---|---|---|
INVALID_KEY |
InvalidLicenseKeyException |
Wrong key format or unknown key |
LICENSE_ALREADY_USED |
LicenseAlreadyUsedException |
Key in use on another device |
LICENSE_EXPIRED |
LicenseExpiredException |
Subscription ended |
LICENSE_REVOKED |
LicenseRevokedException |
Revoked by admin |
MAX_DEVICES_EXCEEDED |
MaxDevicesExceededException |
Too many activations |
TRIAL_USED |
TrialAlreadyUsedException |
Trial already used on device |
CLOCK_TAMPER |
ClockTamperingException |
System clock manipulation |
DEVICE_MISMATCH |
DeviceMismatchException |
License bound to different device |
OFFLINE_LIMIT |
OfflineLimitExceededException |
Grace period exhausted |
API_TIMEOUT |
ApiTimeoutException |
Server unreachable |
SIGNATURE_INVALID |
SignatureVerificationException |
RSA signature mismatch |
- Change
appSecretβ use a strong random string unique per app. - Set
publicKeyβ provide your RSA-2048 public key PEM for full signature verification. - Enable tamper checks β set
enableEmulatorCheck: trueandenableDebuggerCheck: truein release builds. - Use HTTPS β the API client enforces TLS; never deploy with HTTP in production.
- Keep grace period short β 7 days is a good default; less for high-security apps.
- Rotate
appSecreton major versions β triggers re-validation for all users. - Monitor tamper reports β check your server's tamper log for suspicious patterns.
| Tier | Price | Includes |
|---|---|---|
| Open Source | Free | Core + 5 presets |
| ## π Pro Plan β $49 / year | $49 / year |
β All 20+ presets
β Advanced gradients system
β Cloud sync
β Priority updates |
π π Get Pro Access
Built with β€οΈ for the Flutter community