Skip to content

Complete Example

import 'package:flutter/material.dart';
import 'package:alphyn_sdk/alphyn_sdk.dart';
import 'dart:async';
class SecurityScreen extends StatefulWidget {
@override
_SecurityScreenState createState() => _SecurityScreenState();
}
class _SecurityScreenState extends State<SecurityScreen> {
bool _isInitialized = false;
String _deviceId = '';
String _appHash = '';
List<String> _scanResults = [];
List<AlphynCallbackResult> _securityEvents = [];
StreamSubscription<AlphynCallbackResult>? _eventSubscription;
@override
void initState() {
super.initState();
_initializeSdk();
_setupSecurityListener();
}
@override
void dispose() {
_eventSubscription?.cancel();
super.dispose();
}
Future<void> _initializeSdk() async {
try {
// Check initialization status (SDK is initialized natively)
final initialized = await AlphynSdk.isInitialized();
if (initialized == true) {
setState(() {
_isInitialized = true;
});
// Load device information
await _loadDeviceInfo();
// Perform security scan
await _performScan();
}
} catch (e) {
print('SDK check failed: $e');
}
}
void _setupSecurityListener() {
// Subscribe to security events stream
_eventSubscription = AlphynSdk.securityEvents().listen(
(event) {
setState(() {
_securityEvents.insert(0, event);
if (_securityEvents.length > 50) {
_securityEvents = _securityEvents.take(50).toList();
}
});
},
onError: (error) {
print('Security events error: $error');
},
);
}
Future<void> _loadDeviceInfo() async {
final deviceId = await AlphynSdk.getDeviceId();
final appHash = await AlphynSdk.getAppHash();
setState(() {
_deviceId = deviceId;
_appHash = appHash;
});
}
Future<void> _performScan() async {
final scanResult = await AlphynSdk.getScanResult();
// getRejectReasons() returns a newline-separated string; split it into a list
final rejectReasonsRaw = await AlphynSdk.getRejectReasons();
final rejectReasons = rejectReasonsRaw.split('\n').where((line) => line.trim().isNotEmpty).toList();
setState(() {
_scanResults = [];
if (scanResult != null && scanResult.isNotEmpty) {
_scanResults.add(scanResult);
}
if (rejectReasons.isNotEmpty) {
_scanResults.addAll(rejectReasons);
}
});
}
Future<void> _verifyTestAction() async {
try {
// signAction signs with an enrolled user's hardware key: enrollForMfa(userId) must have
// run once on this device first. See https://docs.byteria.dev/mfa/
final result = await AlphynSdk.signAction(
userId: userId,
actionLabel: 'test_action',
context: {
'timestamp': DateTime.now().toIso8601String(),
'source': 'example_app',
},
);
if (result.success) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Action verified! Token: ${result.token}')),
);
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Verification failed: ${result.errorMessage}')),
);
}
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error: $e')),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Security Dashboard')),
body: _isInitialized
? SingleChildScrollView(
padding: EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Device ID: $_deviceId', style: TextStyle(fontWeight: FontWeight.bold)),
SizedBox(height: 8),
Text('App Hash: $_appHash', style: TextStyle(fontWeight: FontWeight.bold)),
SizedBox(height: 16),
Text('Scan Results:', style: TextStyle(fontWeight: FontWeight.bold)),
..._scanResults.map((result) => Padding(
padding: EdgeInsets.only(left: 16, top: 4),
child: Text(result),
)),
SizedBox(height: 16),
ElevatedButton(
onPressed: _verifyTestAction,
child: Text('Verify Test Action'),
),
SizedBox(height: 16),
Text('Security Events (${_securityEvents.length}):', style: TextStyle(fontWeight: FontWeight.bold)),
..._securityEvents.take(10).map((event) => Padding(
padding: EdgeInsets.only(left: 16, top: 4),
child: Text('${event.originalEventType.name}: ${event.message}'),
)),
],
),
)
: Center(child: CircularProgressIndicator()),
);
}
}