import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:local_auth/local_auth.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:login_vault_app/constants.dart'; /// Handles app-level authentication, session, and local identity. class AuthService { final FlutterSecureStorage _storage = const FlutterSecureStorage(); final LocalAuthentication _localAuth = LocalAuthentication(); // ---------- Identity (email + app password) ---------- Future getEmail() async => await _storage.read(key: AppConstants.secureKeyEmail); Future getAppPassword() async => await _storage.read(key: AppConstants.secureKeyAppPassword); Future isRegistered() async => (await getEmail()) != null; Future registerWithEmail(String email, String appPassword) async { await _storage.write(key: AppConstants.secureKeyEmail, value: email); await _storage.write( key: AppConstants.secureKeyAppPassword, value: appPassword); } Future registerWithGoogle(String email) async { await _storage.write(key: AppConstants.secureKeyEmail, value: email); final existing = await getAppPassword(); if (existing == null) { await _storage.write( key: AppConstants.secureKeyAppPassword, value: '__google__'); } } /// Verify the entered app password against the stored one. Future verifyPassword(String password) async { final stored = await getAppPassword(); if (stored == null) return false; if (stored == '__google__') return true; // google users: any pass ok return stored == password; } Future changePassword(String newPassword) async { await _storage.write( key: AppConstants.secureKeyAppPassword, value: newPassword); } // ---------- Biometric (fingerprint) ---------- /// Can the device authenticate with biometrics (fingerprint etc.)? Future canUseBiometrics() async { try { final supported = await _localAuth.isDeviceSupported(); if (!supported) return false; final available = await _localAuth.getAvailableBiometrics(); return available.isNotEmpty; } catch (_) { return false; } } /// Prompt the OS biometric dialog. Returns true on success. Future authenticateWithBiometrics() async { try { return await _localAuth.authenticate( localizedReason: 'Gunakan sidik jari untuk membuka Login Vault', options: const AuthenticationOptions( biometricOnly: true, stickyAuth: true, ), ); } catch (_) { return false; } } // ---------- Session ---------- /// Persist that a session was just opened (with timestamp). Future openSession() async { await _storage.write( key: AppConstants.secureKeySession, value: DateTime.now().toIso8601String()); } Future closeSession() async { await _storage.delete(key: AppConstants.secureKeySession); } /// Returns true if a valid, non-expired session exists. /// [timeoutMinutes] = 0 means "stay logged in until manual logout". Future hasValidSession(int timeoutMinutes) async { if (timeoutMinutes <= 0) { // never auto-expire; just check a session was opened final v = await _storage.read(key: AppConstants.secureKeySession); return v != null; } final v = await _storage.read(key: AppConstants.secureKeySession); if (v == null) return false; final opened = DateTime.tryParse(v); if (opened == null) return false; final diff = DateTime.now().difference(opened).inMinutes; return diff < timeoutMinutes; } // ---------- Timeout setting ---------- /// Get configured session timeout (minutes). Default 3. Future getTimeoutMinutes() async { final sp = await _prefs(); return sp.getInt(AppConstants.prefTimeout) ?? 3; } Future setTimeoutMinutes(int minutes) async { final sp = await _prefs(); await sp.setInt(AppConstants.prefTimeout, minutes); } // ---------- Biometric toggle setting ---------- Future isBiometricEnabled() async { final sp = await _prefs(); return sp.getBool(AppConstants.prefBiometric) ?? false; } Future setBiometricEnabled(bool on) async { final sp = await _prefs(); await sp.setBool(AppConstants.prefBiometric, on); } Future _prefs() async => await SharedPreferences.getInstance(); Future reset() async { await _storage.delete(key: AppConstants.secureKeyEmail); await _storage.delete(key: AppConstants.secureKeyAppPassword); await _storage.delete(key: AppConstants.secureKeySession); } }