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

* fix: Cake 2FA setup issue

* fix: 2FA Setup issue

* fix: 2FA setup bug
This commit is contained in:
Adegoke David 2023-09-28 19:40:15 +01:00 committed by GitHub
parent dc36c31197
commit f07062d987
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 30 additions and 34 deletions

View file

@ -360,7 +360,7 @@ Future<void> setup({
(onAuthFinished, closable) => AuthPage(getIt.get<AuthViewModel>(), (onAuthFinished, closable) => AuthPage(getIt.get<AuthViewModel>(),
onAuthenticationFinished: onAuthFinished, closable: closable)); onAuthenticationFinished: onAuthFinished, closable: closable));
getIt.registerFactory<Setup2FAViewModel>( getIt.registerLazySingleton<Setup2FAViewModel>(
() => Setup2FAViewModel( () => Setup2FAViewModel(
getIt.get<SettingsStore>(), getIt.get<SettingsStore>(),
getIt.get<SharedPreferences>(), getIt.get<SharedPreferences>(),

View file

@ -19,7 +19,6 @@ class PreferencesKey {
'allow_biometrical_authentication'; 'allow_biometrical_authentication';
static const useTOTP2FA = 'use_totp_2fa'; static const useTOTP2FA = 'use_totp_2fa';
static const failedTotpTokenTrials = 'failed_token_trials'; static const failedTotpTokenTrials = 'failed_token_trials';
static const totpSecretKey = 'totp_qr_secret_key';
static const disableExchangeKey = 'disable_exchange'; static const disableExchangeKey = 'disable_exchange';
static const exchangeStatusKey = 'exchange_status'; static const exchangeStatusKey = 'exchange_status';
static const currentTheme = 'current_theme'; static const currentTheme = 'current_theme';
@ -75,4 +74,5 @@ class PreferencesKey {
static const shouldRequireTOTP2FAForAllSecurityAndBackupSettings = static const shouldRequireTOTP2FAForAllSecurityAndBackupSettings =
'should_require_totp_2fa_for_all_security_and_backup_settings'; 'should_require_totp_2fa_for_all_security_and_backup_settings';
static const selectedCake2FAPreset = 'selected_cake_2fa_preset'; static const selectedCake2FAPreset = 'selected_cake_2fa_preset';
static const totpSecretKey = 'totp_secret_key';
} }

View file

@ -53,8 +53,10 @@ class Setup2FAPage extends BasePage {
SizedBox(height: 86), SizedBox(height: 86),
SettingsCellWithArrow( SettingsCellWithArrow(
title: S.current.setup_totp_recommended, title: S.current.setup_totp_recommended,
handler: (_) => Navigator.of(context) handler: (_) {
.pushReplacementNamed(Routes.setup_2faQRPage), setup2FAViewModel.generateSecretKey();
return Navigator.of(context).pushReplacementNamed(Routes.setup_2faQRPage);
},
), ),
StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)),
], ],

View file

@ -89,7 +89,7 @@ class Setup2FAQRPage extends BasePage {
), ),
SizedBox(height: 8), SizedBox(height: 8),
Text( Text(
'${setup2FAViewModel.secretKey}', '${setup2FAViewModel.totpSecretKey}',
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.w700, fontWeight: FontWeight.w700,
@ -108,7 +108,7 @@ class Setup2FAQRPage extends BasePage {
child: InkWell( child: InkWell(
onTap: () { onTap: () {
ClipboardUtil.setSensitiveDataToClipboard( ClipboardUtil.setSensitiveDataToClipboard(
ClipboardData(text: '${setup2FAViewModel.secretKey}')); ClipboardData(text: '${setup2FAViewModel.totpSecretKey}'));
showBar<void>(context, S.of(context).copied_to_clipboard); showBar<void>(context, S.of(context).copied_to_clipboard);
}, },
child: Container( child: Container(

View file

@ -280,14 +280,13 @@ abstract class SettingsStoreBase with Store {
reaction( reaction(
(_) => useTOTP2FA, (bool use) => sharedPreferences.setBool(PreferencesKey.useTOTP2FA, use)); (_) => useTOTP2FA, (bool use) => sharedPreferences.setBool(PreferencesKey.useTOTP2FA, use));
reaction((_) => totpSecretKey,
(String totpKey) => sharedPreferences.setString(PreferencesKey.totpSecretKey, totpKey));
reaction( reaction(
(_) => numberOfFailedTokenTrials, (_) => numberOfFailedTokenTrials,
(int failedTokenTrail) => (int failedTokenTrail) =>
sharedPreferences.setInt(PreferencesKey.failedTotpTokenTrials, failedTokenTrail)); sharedPreferences.setInt(PreferencesKey.failedTotpTokenTrials, failedTokenTrail));
reaction((_) => totpSecretKey,
(String totpKey) => sharedPreferences.setString(PreferencesKey.totpSecretKey, totpKey));
reaction( reaction(
(_) => shouldShowMarketPlaceInDashboard, (_) => shouldShowMarketPlaceInDashboard,
(bool value) => (bool value) =>
@ -422,15 +421,10 @@ abstract class SettingsStoreBase with Store {
bool shouldRequireTOTP2FAForAllSecurityAndBackupSettings; bool shouldRequireTOTP2FAForAllSecurityAndBackupSettings;
@observable @observable
String totpSecretKey; bool useTOTP2FA;
@computed
String get totpVersionOneLink {
return 'otpauth://totp/Cake%20Wallet:$deviceName?secret=$totpSecretKey&issuer=Cake%20Wallet&algorithm=SHA512&digits=8&period=30';
}
@observable @observable
bool useTOTP2FA; String totpSecretKey;
@observable @observable
int numberOfFailedTokenTrials; int numberOfFailedTokenTrials;
@ -575,8 +569,8 @@ abstract class SettingsStoreBase with Store {
final shouldRequireTOTP2FAForAllSecurityAndBackupSettings = sharedPreferences final shouldRequireTOTP2FAForAllSecurityAndBackupSettings = sharedPreferences
.getBool(PreferencesKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings) ?? .getBool(PreferencesKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings) ??
false; false;
final totpSecretKey = sharedPreferences.getString(PreferencesKey.totpSecretKey) ?? '';
final useTOTP2FA = sharedPreferences.getBool(PreferencesKey.useTOTP2FA) ?? false; final useTOTP2FA = sharedPreferences.getBool(PreferencesKey.useTOTP2FA) ?? false;
final totpSecretKey = sharedPreferences.getString(PreferencesKey.totpSecretKey) ?? '';
final tokenTrialNumber = sharedPreferences.getInt(PreferencesKey.failedTotpTokenTrials) ?? 0; final tokenTrialNumber = sharedPreferences.getInt(PreferencesKey.failedTotpTokenTrials) ?? 0;
final shouldShowMarketPlaceInDashboard = final shouldShowMarketPlaceInDashboard =
sharedPreferences.getBool(PreferencesKey.shouldShowMarketPlaceInDashboard) ?? true; sharedPreferences.getBool(PreferencesKey.shouldShowMarketPlaceInDashboard) ?? true;
@ -677,8 +671,8 @@ abstract class SettingsStoreBase with Store {
initialFiatMode: currentFiatApiMode, initialFiatMode: currentFiatApiMode,
initialAllowBiometricalAuthentication: allowBiometricalAuthentication, initialAllowBiometricalAuthentication: allowBiometricalAuthentication,
initialCake2FAPresetOptions: selectedCake2FAPreset, initialCake2FAPresetOptions: selectedCake2FAPreset,
initialTotpSecretKey: totpSecretKey,
initialUseTOTP2FA: useTOTP2FA, initialUseTOTP2FA: useTOTP2FA,
initialTotpSecretKey: totpSecretKey,
initialFailedTokenTrial: tokenTrialNumber, initialFailedTokenTrial: tokenTrialNumber,
initialExchangeStatus: exchangeStatus, initialExchangeStatus: exchangeStatus,
initialTheme: savedTheme, initialTheme: savedTheme,
@ -752,9 +746,8 @@ abstract class SettingsStoreBase with Store {
shouldSaveRecipientAddress = shouldSaveRecipientAddress =
sharedPreferences.getBool(PreferencesKey.shouldSaveRecipientAddressKey) ?? sharedPreferences.getBool(PreferencesKey.shouldSaveRecipientAddressKey) ??
shouldSaveRecipientAddress; shouldSaveRecipientAddress;
totpSecretKey = sharedPreferences.getString(PreferencesKey.totpSecretKey) ?? totpSecretKey;
useTOTP2FA = sharedPreferences.getBool(PreferencesKey.useTOTP2FA) ?? useTOTP2FA; useTOTP2FA = sharedPreferences.getBool(PreferencesKey.useTOTP2FA) ?? useTOTP2FA;
totpSecretKey = sharedPreferences.getString(PreferencesKey.totpSecretKey) ?? totpSecretKey;
numberOfFailedTokenTrials = numberOfFailedTokenTrials =
sharedPreferences.getInt(PreferencesKey.failedTotpTokenTrials) ?? numberOfFailedTokenTrials; sharedPreferences.getInt(PreferencesKey.failedTotpTokenTrials) ?? numberOfFailedTokenTrials;
isAppSecure = sharedPreferences.getBool(PreferencesKey.isAppSecureKey) ?? isAppSecure; isAppSecure = sharedPreferences.getBool(PreferencesKey.isAppSecureKey) ?? isAppSecure;

View file

@ -27,7 +27,6 @@ abstract class Setup2FAViewModelBase with Store {
unhighlightTabs = false, unhighlightTabs = false,
selected2FASettings = ObservableList<VerboseControlSettings>(), selected2FASettings = ObservableList<VerboseControlSettings>(),
state = InitialExecutionState() { state = InitialExecutionState() {
_getRandomBase32SecretKey();
selectCakePreset(selectedCake2FAPreset); selectCakePreset(selectedCake2FAPreset);
reaction((_) => state, _saveLastAuthTime); reaction((_) => state, _saveLastAuthTime);
} }
@ -36,9 +35,12 @@ abstract class Setup2FAViewModelBase with Store {
static const banTimeout = 180; // 3 minutes static const banTimeout = 180; // 3 minutes
final banTimeoutKey = S.current.auth_store_ban_timeout; final banTimeoutKey = S.current.auth_store_ban_timeout;
String get secretKey => _settingsStore.totpSecretKey;
String get deviceName => _settingsStore.deviceName; String get deviceName => _settingsStore.deviceName;
String get totpVersionOneLink => _settingsStore.totpVersionOneLink;
@computed
String get totpSecretKey => _settingsStore.totpSecretKey;
String totpVersionOneLink = '';
@observable @observable
ExecutionState state; ExecutionState state;
@ -84,9 +86,14 @@ abstract class Setup2FAViewModelBase with Store {
bool get shouldRequireTOTP2FAForAllSecurityAndBackupSettings => bool get shouldRequireTOTP2FAForAllSecurityAndBackupSettings =>
_settingsStore.shouldRequireTOTP2FAForAllSecurityAndBackupSettings; _settingsStore.shouldRequireTOTP2FAForAllSecurityAndBackupSettings;
void _getRandomBase32SecretKey() { @action
final randomBase32Key = Utils.generateRandomBase32SecretKey(16); void generateSecretKey() {
_setBase32SecretKey(randomBase32Key); final _totpSecretKey = Utils.generateRandomBase32SecretKey(16);
totpVersionOneLink =
'otpauth://totp/Cake%20Wallet:$deviceName?secret=$_totpSecretKey&issuer=Cake%20Wallet&algorithm=SHA512&digits=8&period=30';
setTOTPSecretKey(_totpSecretKey);
} }
@action @action
@ -95,15 +102,10 @@ abstract class Setup2FAViewModelBase with Store {
} }
@action @action
void _setBase32SecretKey(String value) { void setTOTPSecretKey(String value) {
_settingsStore.totpSecretKey = value; _settingsStore.totpSecretKey = value;
} }
@action
void clearBase32SecretKey() {
_settingsStore.totpSecretKey = '';
}
Duration? banDuration() { Duration? banDuration() {
final unbanTimestamp = _sharedPreferences.getInt(banTimeoutKey); final unbanTimestamp = _sharedPreferences.getInt(banTimeoutKey);
@ -145,7 +147,7 @@ abstract class Setup2FAViewModelBase with Store {
} }
final result = Utils.verify( final result = Utils.verify(
secretKey: secretKey, secretKey: totpSecretKey,
otp: otpText, otp: otpText,
); );
@ -156,7 +158,6 @@ abstract class Setup2FAViewModelBase with Store {
} else { } else {
final value = _settingsStore.numberOfFailedTokenTrials + 1; final value = _settingsStore.numberOfFailedTokenTrials + 1;
adjustTokenTrialNumber(value); adjustTokenTrialNumber(value);
print(value);
if (_failureCounter >= maxFailedTrials) { if (_failureCounter >= maxFailedTrials) {
final banDuration = await ban(); final banDuration = await ban();
state = AuthenticationBanned( state = AuthenticationBanned(