From 8333f20e04efd1aa160bcdf4367de4e6a2336887 Mon Sep 17 00:00:00 2001 From: Dain Nilsson Date: Wed, 27 Sep 2023 15:12:31 +0200 Subject: [PATCH] Handle CTAP2 forcePinChange. --- lib/fido/models.dart | 2 ++ lib/fido/views/key_actions.dart | 22 +++++++++++++++------- lib/fido/views/locked_page.dart | 11 +++++++++++ lib/fido/views/pin_dialog.dart | 2 +- lib/l10n/app_en.arb | 3 +++ 5 files changed, 32 insertions(+), 8 deletions(-) diff --git a/lib/fido/models.dart b/lib/fido/models.dart index 1aa139be..79b4d1cf 100755 --- a/lib/fido/models.dart +++ b/lib/fido/models.dart @@ -43,6 +43,8 @@ class FidoState with _$FidoState { bool? get bioEnroll => info['options']['bioEnroll']; bool get alwaysUv => info['options']['alwaysUv'] == true; + + bool get forcePinChange => info['force_pin_change'] == true; } @freezed diff --git a/lib/fido/views/key_actions.dart b/lib/fido/views/key_actions.dart index e2d153ab..381732fe 100755 --- a/lib/fido/views/key_actions.dart +++ b/lib/fido/views/key_actions.dart @@ -28,12 +28,16 @@ import 'pin_dialog.dart'; import 'reset_dialog.dart'; bool fidoShowActionsNotifier(FidoState state) { - return (state.alwaysUv && !state.hasPin) || state.bioEnroll == false; + return (state.alwaysUv && !state.hasPin) || + state.bioEnroll == false || + state.forcePinChange; } Widget fidoBuildActions( BuildContext context, DeviceNode node, FidoState state, int fingerprints) { final l10n = AppLocalizations.of(context)!; + final colors = Theme.of(context).buttonTheme.colorScheme ?? + Theme.of(context).colorScheme; return FsDialog( child: Column( @@ -52,8 +56,9 @@ Widget fidoBuildActions( : state.hasPin ? l10n.l_unlock_pin_first : l10n.l_set_pin_first, - trailing: - fingerprints == 0 ? const Icon(Icons.warning_amber) : null, + trailing: fingerprints == 0 + ? Icon(Icons.warning_amber, color: colors.tertiary) + : null, onTap: state.unlocked && fingerprints < 5 ? (context) { Navigator.of(context).pop(); @@ -74,11 +79,14 @@ Widget fidoBuildActions( icon: const Icon(Icons.pin_outlined), title: state.hasPin ? l10n.s_change_pin : l10n.s_set_pin, subtitle: state.hasPin - ? l10n.s_fido_pin_protection + ? (state.forcePinChange + ? l10n.s_pin_change_required + : l10n.s_fido_pin_protection) : l10n.l_fido_pin_protection_optional, - trailing: state.alwaysUv && !state.hasPin - ? const Icon(Icons.warning_amber) - : null, + trailing: + state.alwaysUv && !state.hasPin || state.forcePinChange + ? Icon(Icons.warning_amber, color: colors.tertiary) + : null, onTap: (context) { Navigator.of(context).pop(); showBlurDialog( diff --git a/lib/fido/views/locked_page.dart b/lib/fido/views/locked_page.dart index d6cc93e9..e7e0bd55 100755 --- a/lib/fido/views/locked_page.dart +++ b/lib/fido/views/locked_page.dart @@ -66,6 +66,17 @@ class FidoLockedPage extends ConsumerWidget { header: l10n.l_ready_to_use, message: l10n.l_register_sk_on_websites, keyActionsBuilder: _buildActions, + keyActionsBadge: fidoShowActionsNotifier(state), + ); + } + + if (state.forcePinChange) { + return MessagePage( + title: Text(l10n.s_webauthn), + header: l10n.s_pin_change_required, + message: l10n.l_pin_change_required_desc, + keyActionsBuilder: _buildActions, + keyActionsBadge: fidoShowActionsNotifier(state), ); } diff --git a/lib/fido/views/pin_dialog.dart b/lib/fido/views/pin_dialog.dart index c70487c4..e80c27c8 100755 --- a/lib/fido/views/pin_dialog.dart +++ b/lib/fido/views/pin_dialog.dart @@ -71,7 +71,7 @@ class _FidoPinDialogState extends ConsumerState { crossAxisAlignment: CrossAxisAlignment.start, children: [ if (hasPin) ...[ - Text(l10n.p_enter_current_pin_or_reset), + Text(l10n.p_enter_current_pin_or_reset_no_puk), TextFormField( initialValue: _currentPin, autofocus: true, diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index eccd8923..a7b893bf 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -222,6 +222,7 @@ } }, "s_fido_pin_protection": "FIDO PIN protection", + "s_pin_change_required": "PIN change required", "l_fido_pin_protection_optional": "Optional FIDO PIN protection", "l_enter_fido2_pin": "Enter the FIDO2 PIN for your YubiKey", "l_optionally_set_a_pin": "Optionally set a PIN to protect access to your YubiKey\nRegister as a Security Key on websites", @@ -229,7 +230,9 @@ "l_set_pin_first": "A PIN is required first", "l_unlock_pin_first": "Unlock with PIN first", "l_pin_soft_locked": "PIN has been blocked until the YubiKey is removed and reinserted", + "l_pin_change_required_desc": "A new PIN must be set before you can use this application", "p_enter_current_pin_or_reset": "Enter your current PIN. If you don't know your PIN, you'll need to unblock it with the PUK or reset the YubiKey.", + "p_enter_current_pin_or_reset_no_puk": "Enter your current PIN. If you don't know your PIN, you'll need to reset the YubiKey.", "p_enter_current_puk_or_reset": "Enter your current PUK. If you don't know your PUK, you'll need to reset the YubiKey.", "p_enter_new_fido2_pin": "Enter your new PIN. A PIN must be at least {length} characters long and may contain letters, numbers and special characters.", "@p_enter_new_fido2_pin" : {