X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/916a82616f1e2c750a1f01109e65ad2b603a79ce..refs/pull/3693/head:/app/Http/Controllers/Auth/MfaController.php diff --git a/app/Http/Controllers/Auth/MfaController.php b/app/Http/Controllers/Auth/MfaController.php index 8ddccaa98..6f6beb873 100644 --- a/app/Http/Controllers/Auth/MfaController.php +++ b/app/Http/Controllers/Auth/MfaController.php @@ -4,69 +4,70 @@ namespace BookStack\Http\Controllers\Auth; use BookStack\Actions\ActivityType; use BookStack\Auth\Access\Mfa\MfaValue; -use BookStack\Auth\Access\Mfa\TotpService; -use BookStack\Auth\Access\Mfa\TotpValidationRule; use BookStack\Http\Controllers\Controller; use Illuminate\Http\Request; -use Illuminate\Validation\ValidationException; class MfaController extends Controller { - protected const TOTP_SETUP_SECRET_SESSION_KEY = 'mfa-setup-totp-secret'; + use HandlesPartialLogins; /** * Show the view to setup MFA for the current user. */ public function setup() { - $userMethods = user()->mfaValues() + $userMethods = $this->currentOrLastAttemptedUser() + ->mfaValues() ->get(['id', 'method']) ->groupBy('method'); + + $this->setPageTitle(trans('auth.mfa_setup')); + return view('mfa.setup', [ 'userMethods' => $userMethods, ]); } /** - * Show a view that generates and displays a TOTP QR code. + * Remove an MFA method for the current user. + * + * @throws \Exception */ - public function totpGenerate(TotpService $totp) + public function remove(string $method) { - if (session()->has(static::TOTP_SETUP_SECRET_SESSION_KEY)) { - $totpSecret = decrypt(session()->get(static::TOTP_SETUP_SECRET_SESSION_KEY)); - } else { - $totpSecret = $totp->generateSecret(); - session()->put(static::TOTP_SETUP_SECRET_SESSION_KEY, encrypt($totpSecret)); + if (in_array($method, MfaValue::allMethods())) { + $value = user()->mfaValues()->where('method', '=', $method)->first(); + if ($value) { + $value->delete(); + $this->logActivity(ActivityType::MFA_REMOVE_METHOD, $method); + } } - $qrCodeUrl = $totp->generateUrl($totpSecret); - $svg = $totp->generateQrCodeSvg($qrCodeUrl); - - return view('mfa.totp-generate', [ - 'secret' => $totpSecret, - 'svg' => $svg, - ]); + return redirect('/mfa/setup'); } /** - * Confirm the setup of TOTP and save the auth method secret - * against the current user. - * @throws ValidationException + * Show the page to start an MFA verification. */ - public function totpConfirm(Request $request) + public function verify(Request $request) { - $totpSecret = decrypt(session()->get(static::TOTP_SETUP_SECRET_SESSION_KEY)); - $this->validate($request, [ - 'code' => [ - 'required', - 'max:12', 'min:4', - new TotpValidationRule($totpSecret), - ] - ]); + $desiredMethod = $request->get('method'); + $userMethods = $this->currentOrLastAttemptedUser() + ->mfaValues() + ->get(['id', 'method']) + ->groupBy('method'); - MfaValue::upsertWithValue(user(), MfaValue::METHOD_TOTP, $totpSecret); - $this->logActivity(ActivityType::MFA_SETUP_METHOD, 'totp'); + // Basic search for the default option for a user. + // (Prioritises totp over backup codes) + $method = $userMethods->has($desiredMethod) ? $desiredMethod : $userMethods->keys()->sort()->reverse()->first(); + $otherMethods = $userMethods->keys()->filter(function ($userMethod) use ($method) { + return $method !== $userMethod; + })->all(); - return redirect('/mfa/setup'); + return view('mfa.verify', [ + 'userMethods' => $userMethods, + 'method' => $method, + 'otherMethods' => $otherMethods, + ]); } }