mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-01-22 02:34:59 +00:00
fix: Cake-2FA-setup-issue (#1097)
* fix: Cake 2FA setup issue * fix: 2FA Setup issue * fix: 2FA setup bug
This commit is contained in:
parent
dc36c31197
commit
f07062d987
6 changed files with 30 additions and 34 deletions
|
@ -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>(),
|
||||||
|
|
|
@ -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';
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)),
|
||||||
],
|
],
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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(
|
||||||
|
|
Loading…
Reference in a new issue