fix: Cake-2FA-setup-issue (#1097)

* fix: Cake 2FA setup issue * fix: 2FA Setup issue * fix: 2FA setup bug

Adegoke David committed Sep 28, 2023 at 19:40 UTC f07062d9879bfc9e4fb0ed4df318fa525add1785
6 files changed +30 -34
lib/di.dart
+1 -1
@@ -360,7 +360,7 @@ Future<void> setup({
360 (onAuthFinished, closable) => AuthPage(getIt.get<AuthViewModel>(),
361 onAuthenticationFinished: onAuthFinished, closable: closable));
362
363 - getIt.registerFactory<Setup2FAViewModel>(
363 + getIt.registerLazySingleton<Setup2FAViewModel>(
364 () => Setup2FAViewModel(
365 getIt.get<SettingsStore>(),
366 getIt.get<SharedPreferences>(),
lib/entities/preferences_key.dart
+1 -1
@@ -19,7 +19,6 @@ class PreferencesKey {
19 'allow_biometrical_authentication';
20 static const useTOTP2FA = 'use_totp_2fa';
21 static const failedTotpTokenTrials = 'failed_token_trials';
22 - static const totpSecretKey = 'totp_qr_secret_key';
22 static const disableExchangeKey = 'disable_exchange';
23 static const exchangeStatusKey = 'exchange_status';
24 static const currentTheme = 'current_theme';
@@ -75,4 +74,5 @@ class PreferencesKey {
74 static const shouldRequireTOTP2FAForAllSecurityAndBackupSettings =
75 'should_require_totp_2fa_for_all_security_and_backup_settings';
76 static const selectedCake2FAPreset = 'selected_cake_2fa_preset';
77 + static const totpSecretKey = 'totp_secret_key';
78 }
lib/src/screens/setup_2fa/setup_2fa.dart
+4 -2
@@ -53,8 +53,10 @@ class Setup2FAPage extends BasePage {
53 SizedBox(height: 86),
54 SettingsCellWithArrow(
55 title: S.current.setup_totp_recommended,
56 - handler: (_) => Navigator.of(context)
57 - .pushReplacementNamed(Routes.setup_2faQRPage),
56 + handler: (_) {
57 + setup2FAViewModel.generateSecretKey();
58 + return Navigator.of(context).pushReplacementNamed(Routes.setup_2faQRPage);
59 + },
60 ),
61 StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)),
62 ],
lib/src/screens/setup_2fa/setup_2fa_qr_page.dart
+2 -2
@@ -89,7 +89,7 @@ class Setup2FAQRPage extends BasePage {
89 ),
90 SizedBox(height: 8),
91 Text(
92 - '${setup2FAViewModel.secretKey}',
92 + '${setup2FAViewModel.totpSecretKey}',
93 style: TextStyle(
94 fontSize: 16,
95 fontWeight: FontWeight.w700,
@@ -108,7 +108,7 @@ class Setup2FAQRPage extends BasePage {
108 child: InkWell(
109 onTap: () {
110 ClipboardUtil.setSensitiveDataToClipboard(
111 - ClipboardData(text: '${setup2FAViewModel.secretKey}'));
111 + ClipboardData(text: '${setup2FAViewModel.totpSecretKey}'));
112 showBar<void>(context, S.of(context).copied_to_clipboard);
113 },
114 child: Container(
lib/store/settings_store.dart
+7 -14
@@ -280,14 +280,13 @@ abstract class SettingsStoreBase with Store {
280 reaction(
281 (_) => useTOTP2FA, (bool use) => sharedPreferences.setBool(PreferencesKey.useTOTP2FA, use));
282
283 + reaction((_) => totpSecretKey,
284 + (String totpKey) => sharedPreferences.setString(PreferencesKey.totpSecretKey, totpKey));
285 reaction(
286 (_) => numberOfFailedTokenTrials,
287 (int failedTokenTrail) =>
288 sharedPreferences.setInt(PreferencesKey.failedTotpTokenTrials, failedTokenTrail));
289
288 - reaction((_) => totpSecretKey,
289 - (String totpKey) => sharedPreferences.setString(PreferencesKey.totpSecretKey, totpKey));
290 -
290 reaction(
291 (_) => shouldShowMarketPlaceInDashboard,
292 (bool value) =>
@@ -422,15 +421,10 @@ abstract class SettingsStoreBase with Store {
421 bool shouldRequireTOTP2FAForAllSecurityAndBackupSettings;
422
423 @observable
425 - String totpSecretKey;
426 -
427 - @computed
428 - String get totpVersionOneLink {
429 - return 'otpauth://totp/Cake%20Wallet:$deviceName?secret=$totpSecretKey&issuer=Cake%20Wallet&algorithm=SHA512&digits=8&period=30';
430 - }
424 + bool useTOTP2FA;
425
426 @observable
433 - bool useTOTP2FA;
427 + String totpSecretKey;
428
429 @observable
430 int numberOfFailedTokenTrials;
@@ -575,8 +569,8 @@ abstract class SettingsStoreBase with Store {
569 final shouldRequireTOTP2FAForAllSecurityAndBackupSettings = sharedPreferences
570 .getBool(PreferencesKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings) ??
571 false;
578 - final totpSecretKey = sharedPreferences.getString(PreferencesKey.totpSecretKey) ?? '';
572 final useTOTP2FA = sharedPreferences.getBool(PreferencesKey.useTOTP2FA) ?? false;
573 + final totpSecretKey = sharedPreferences.getString(PreferencesKey.totpSecretKey) ?? '';
574 final tokenTrialNumber = sharedPreferences.getInt(PreferencesKey.failedTotpTokenTrials) ?? 0;
575 final shouldShowMarketPlaceInDashboard =
576 sharedPreferences.getBool(PreferencesKey.shouldShowMarketPlaceInDashboard) ?? true;
@@ -677,8 +671,8 @@ abstract class SettingsStoreBase with Store {
671 initialFiatMode: currentFiatApiMode,
672 initialAllowBiometricalAuthentication: allowBiometricalAuthentication,
673 initialCake2FAPresetOptions: selectedCake2FAPreset,
680 - initialTotpSecretKey: totpSecretKey,
674 initialUseTOTP2FA: useTOTP2FA,
675 + initialTotpSecretKey: totpSecretKey,
676 initialFailedTokenTrial: tokenTrialNumber,
677 initialExchangeStatus: exchangeStatus,
678 initialTheme: savedTheme,
@@ -752,9 +746,8 @@ abstract class SettingsStoreBase with Store {
746 shouldSaveRecipientAddress =
747 sharedPreferences.getBool(PreferencesKey.shouldSaveRecipientAddressKey) ??
748 shouldSaveRecipientAddress;
755 - totpSecretKey = sharedPreferences.getString(PreferencesKey.totpSecretKey) ?? totpSecretKey;
749 useTOTP2FA = sharedPreferences.getBool(PreferencesKey.useTOTP2FA) ?? useTOTP2FA;
757 -
750 + totpSecretKey = sharedPreferences.getString(PreferencesKey.totpSecretKey) ?? totpSecretKey;
751 numberOfFailedTokenTrials =
752 sharedPreferences.getInt(PreferencesKey.failedTotpTokenTrials) ?? numberOfFailedTokenTrials;
753 isAppSecure = sharedPreferences.getBool(PreferencesKey.isAppSecureKey) ?? isAppSecure;
lib/view_model/set_up_2fa_viewmodel.dart
+15 -14
@@ -27,7 +27,6 @@ abstract class Setup2FAViewModelBase with Store {
27 unhighlightTabs = false,
28 selected2FASettings = ObservableList<VerboseControlSettings>(),
29 state = InitialExecutionState() {
30 - _getRandomBase32SecretKey();
30 selectCakePreset(selectedCake2FAPreset);
31 reaction((_) => state, _saveLastAuthTime);
32 }
@@ -36,9 +35,12 @@ abstract class Setup2FAViewModelBase with Store {
35 static const banTimeout = 180; // 3 minutes
36 final banTimeoutKey = S.current.auth_store_ban_timeout;
37
39 - String get secretKey => _settingsStore.totpSecretKey;
38 String get deviceName => _settingsStore.deviceName;
41 - String get totpVersionOneLink => _settingsStore.totpVersionOneLink;
39 +
40 + @computed
41 + String get totpSecretKey => _settingsStore.totpSecretKey;
42 +
43 + String totpVersionOneLink = '';
44
45 @observable
46 ExecutionState state;
@@ -84,9 +86,14 @@ abstract class Setup2FAViewModelBase with Store {
86 bool get shouldRequireTOTP2FAForAllSecurityAndBackupSettings =>
87 _settingsStore.shouldRequireTOTP2FAForAllSecurityAndBackupSettings;
88
87 - void _getRandomBase32SecretKey() {
88 - final randomBase32Key = Utils.generateRandomBase32SecretKey(16);
89 - _setBase32SecretKey(randomBase32Key);
89 + @action
90 + void generateSecretKey() {
91 + final _totpSecretKey = Utils.generateRandomBase32SecretKey(16);
92 +
93 + totpVersionOneLink =
94 + 'otpauth://totp/Cake%20Wallet:$deviceName?secret=$_totpSecretKey&issuer=Cake%20Wallet&algorithm=SHA512&digits=8&period=30';
95 +
96 + setTOTPSecretKey(_totpSecretKey);
97 }
98
99 @action
@@ -95,15 +102,10 @@ abstract class Setup2FAViewModelBase with Store {
102 }
103
104 @action
98 - void _setBase32SecretKey(String value) {
105 + void setTOTPSecretKey(String value) {
106 _settingsStore.totpSecretKey = value;
107 }
108
102 - @action
103 - void clearBase32SecretKey() {
104 - _settingsStore.totpSecretKey = '';
105 - }
106 -
109 Duration? banDuration() {
110 final unbanTimestamp = _sharedPreferences.getInt(banTimeoutKey);
111
@@ -145,7 +147,7 @@ abstract class Setup2FAViewModelBase with Store {
147 }
148
149 final result = Utils.verify(
148 - secretKey: secretKey,
150 + secretKey: totpSecretKey,
151 otp: otpText,
152 );
153
@@ -156,7 +158,6 @@ abstract class Setup2FAViewModelBase with Store {
158 } else {
159 final value = _settingsStore.numberOfFailedTokenTrials + 1;
160 adjustTokenTrialNumber(value);
159 - print(value);
161 if (_failureCounter >= maxFailedTrials) {
162 final banDuration = await ban();
163 state = AuthenticationBanned(