Make 2FA code + validation more robust. Thanks to @jtmoss3991, @timaschew and @Ottega.

This commit is contained in:
James Cole
2022-09-04 13:32:59 +02:00
parent 8659c7efbd
commit 06b7f18d55
5 changed files with 37 additions and 27 deletions

View File

@@ -88,7 +88,7 @@ class DebugController extends Controller
public function flush(Request $request) public function flush(Request $request)
{ {
app('preferences')->mark(); app('preferences')->mark();
$request->session()->forget(['start', 'end', '_previous', 'viewRange', 'range', 'is_custom_range']); $request->session()->forget(['start', 'end', '_previous', 'viewRange', 'range', 'is_custom_range','temp-mfa-secret','temp-mfa-codes']);
Log::debug('Call cache:clear...'); Log::debug('Call cache:clear...');
Artisan::call('cache:clear'); Artisan::call('cache:clear');
Log::debug('Call config:clear...'); Log::debug('Call config:clear...');

View File

@@ -34,6 +34,7 @@ use FireflyIII\Http\Requests\ProfileFormRequest;
use FireflyIII\Http\Requests\TokenFormRequest; use FireflyIII\Http\Requests\TokenFormRequest;
use FireflyIII\Models\Preference; use FireflyIII\Models\Preference;
use FireflyIII\Repositories\User\UserRepositoryInterface; use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\Support\Http\Controllers\CreateStuff; use FireflyIII\Support\Http\Controllers\CreateStuff;
use FireflyIII\User; use FireflyIII\User;
use Google2FA; use Google2FA;
@@ -158,36 +159,35 @@ class ProfileController extends Controller
return redirect(route('profile.index')); return redirect(route('profile.index'));
} }
$domain = $this->getDomain(); $domain = $this->getDomain();
$secret = null; $secretPreference = Preferences::get('temp-mfa-secret');
$codesPreference = Preferences::get('temp-mfa-codes');
// generate secret if not in session // generate secret if not in session
if (!session()->has('temp-mfa-secret')) { if (null === $secretPreference) {
// generate secret + store + flash // generate secret + store + flash
$secret = Google2FA::generateSecretKey(); $secret = Google2FA::generateSecretKey();
session()->put('temp-mfa-secret', $secret); Preferences::set('temp-mfa-secret', $secret);
session()->flash('two-factor-secret', $secret);
}
// re-use secret if in session
if (session()->has('temp-mfa-secret')) {
// get secret from session and flash
$secret = session()->get('temp-mfa-secret');
session()->flash('two-factor-secret', $secret);
} }
// generate codes if not in session: // re-use secret if in session
if (null !== $secretPreference) {
// get secret from session and flash
$secret = $secretPreference->data;
}
// generate recovery codes if not in session:
$recoveryCodes = ''; $recoveryCodes = '';
if (!session()->has('temp-mfa-codes')) {
if (null === $codesPreference) {
// generate codes + store + flash: // generate codes + store + flash:
$recovery = app(Recovery::class); $recovery = app(Recovery::class);
$recoveryCodes = $recovery->lowercase()->setCount(8)->setBlocks(2)->setChars(6)->toArray(); $recoveryCodes = $recovery->lowercase()->setCount(8)->setBlocks(2)->setChars(6)->toArray();
session()->put('temp-mfa-codes', $recoveryCodes); Preferences::set('temp-mfa-codes', $recoveryCodes);
session()->flash('two-factor-codes', $recoveryCodes);
} }
// get codes from session if there already: // get codes from session if present already:
if (session()->has('temp-mfa-codes')) { if (null !== $codesPreference) {
$recoveryCodes = session()->get('temp-mfa-codes'); $recoveryCodes = $codesPreference->data;
session()->flash('two-factor-codes', $recoveryCodes);
} }
$codes = implode("\r\n", $recoveryCodes); $codes = implode("\r\n", $recoveryCodes);
@@ -275,7 +275,11 @@ class ProfileController extends Controller
/** @var User $user */ /** @var User $user */
$user = auth()->user(); $user = auth()->user();
Preferences::delete('temp-mfa-secret');
Preferences::delete('temp-mfa-codes');
$repository->setMFACode($user, null); $repository->setMFACode($user, null);
app('preferences')->mark();
session()->flash('success', (string) trans('firefly.pref_two_factor_auth_disabled')); session()->flash('success', (string) trans('firefly.pref_two_factor_auth_disabled'));
session()->flash('info', (string) trans('firefly.pref_two_factor_auth_remove_it')); session()->flash('info', (string) trans('firefly.pref_two_factor_auth_remove_it'));
@@ -498,10 +502,13 @@ class ProfileController extends Controller
$user = auth()->user(); $user = auth()->user();
/** @var UserRepositoryInterface $repository */ /** @var UserRepositoryInterface $repository */
$repository = app(UserRepositoryInterface::class); $repository = app(UserRepositoryInterface::class);
/** @var string $secret */ $secret = (string) session()->get('temp-mfa-secret');
$secret = session()->get('two-factor-secret');
$repository->setMFACode($user, $secret); $repository->setMFACode($user, $secret);
Preferences::delete('temp-mfa-secret');
Preferences::delete('temp-mfa-codes');
session()->flash('success', (string) trans('firefly.saved_preferences')); session()->flash('success', (string) trans('firefly.saved_preferences'));
app('preferences')->mark(); app('preferences')->mark();

View File

@@ -64,7 +64,6 @@ class AuthServiceProvider extends ServiceProvider
); );
$this->registerPolicies(); $this->registerPolicies();
Passport::routes();
Passport::tokensExpireIn(now()->addDays(14)); Passport::tokensExpireIn(now()->addDays(14));
} }
} }

View File

@@ -69,8 +69,6 @@ class RemoteUserProvider implements UserProvider
$roleObject = Role::where('name', 'owner')->first(); $roleObject = Role::where('name', 'owner')->first();
$user->roles()->attach($roleObject); $user->roles()->attach($roleObject);
} }
} }
Log::debug(sprintf('Going to return user #%d (%s)', $user->id, $user->email)); Log::debug(sprintf('Going to return user #%d (%s)', $user->id, $user->email));

View File

@@ -35,6 +35,7 @@ use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Services\Password\Verifier; use FireflyIII\Services\Password\Verifier;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\Support\ParseDateString; use FireflyIII\Support\ParseDateString;
use FireflyIII\TransactionRules\Triggers\TriggerInterface; use FireflyIII\TransactionRules\Triggers\TriggerInterface;
use FireflyIII\User; use FireflyIII\User;
@@ -68,8 +69,13 @@ class FireflyValidator extends Validator
if (null === $value || !is_string($value) || 6 !== strlen($value)) { if (null === $value || !is_string($value) || 6 !== strlen($value)) {
return false; return false;
} }
$user = auth()->user();
$secret = session('two-factor-secret'); if (null === $user) {
Log::error('No user during validate2faCode');
return false;
}
$secretPreference = Preferences::get('temp-mfa-secret');
$secret = $secretPreference?->data ?? '';
return Google2FA::verifyKey($secret, $value); return Google2FA::verifyKey($secret, $value);
} }