yubikey_flutter 0.1.0
yubikey_flutter: ^0.1.0 copied to clipboard
Flutter plugin for YubiKey hardware authentication. Supports OTP, OATH TOTP/HOTP, FIDO2/WebAuthn and HMAC-SHA1 Challenge-Response over NFC, built on the official Yubico yubikit-android SDK.
import 'package:flutter/material.dart';
import 'screens/otp_screen.dart';
import 'screens/oath_screen.dart';
import 'screens/fido2_screen.dart';
void main() {
runApp(const YubikeyDemoApp());
}
class YubikeyDemoApp extends StatelessWidget {
const YubikeyDemoApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'YubiKey Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: const Color(0xFF1B4D3E), // Yubico green
brightness: Brightness.light,
),
useMaterial3: true,
),
home: const HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('YubiKey Flutter Plugin'),
backgroundColor: const Color(0xFF1B4D3E),
foregroundColor: Colors.white,
),
body: Padding(
padding: const EdgeInsets.all(24),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(height: 24),
_FeatureCard(
icon: Icons.vpn_key,
title: 'OTP',
subtitle: 'Read a Yubico OTP via NFC tap',
color: const Color(0xFF1B4D3E),
onTap: () => Navigator.push(
context,
MaterialPageRoute(builder: (_) => const OtpScreen()),
),
),
const SizedBox(height: 16),
_FeatureCard(
icon: Icons.lock_clock,
title: 'OATH TOTP / HOTP',
subtitle: 'List credentials and calculate codes',
color: const Color(0xFF2E7D5A),
onTap: () => Navigator.push(
context,
MaterialPageRoute(builder: (_) => const OathScreen()),
),
),
const SizedBox(height: 16),
_FeatureCard(
icon: Icons.fingerprint,
title: 'FIDO2 / WebAuthn',
subtitle: 'Register and authenticate with passkeys',
color: const Color(0xFF4CAF50),
onTap: () => Navigator.push(
context,
MaterialPageRoute(builder: (_) => const Fido2Screen()),
),
),
],
),
),
);
}
}
class _FeatureCard extends StatelessWidget {
final IconData icon;
final String title;
final String subtitle;
final Color color;
final VoidCallback onTap;
const _FeatureCard({
required this.icon,
required this.title,
required this.subtitle,
required this.color,
required this.onTap,
});
@override
Widget build(BuildContext context) {
return Card(
elevation: 2,
child: ListTile(
contentPadding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
leading: CircleAvatar(
backgroundColor: color,
child: Icon(icon, color: Colors.white),
),
title: Text(title,
style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16)),
subtitle: Text(subtitle),
trailing: const Icon(Icons.arrow_forward_ios, size: 16),
onTap: onTap,
),
);
}
}