X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/d25cd83d8e2a8741a6476ce2d7ff6efc728ecc6e..refs/pull/3365/head:/app/Http/Controllers/Auth/MfaController.php diff --git a/app/Http/Controllers/Auth/MfaController.php b/app/Http/Controllers/Auth/MfaController.php index be381e3b0..6f6beb873 100644 --- a/app/Http/Controllers/Auth/MfaController.php +++ b/app/Http/Controllers/Auth/MfaController.php @@ -2,85 +2,72 @@ namespace BookStack\Http\Controllers\Auth; -use BaconQrCode\Renderer\Color\Rgb; -use BaconQrCode\Renderer\Image\SvgImageBackEnd; -use BaconQrCode\Renderer\ImageRenderer; -use BaconQrCode\Renderer\RendererStyle\Fill; -use BaconQrCode\Renderer\RendererStyle\RendererStyle; -use BaconQrCode\Writer; +use BookStack\Actions\ActivityType; +use BookStack\Auth\Access\Mfa\MfaValue; use BookStack\Http\Controllers\Controller; use Illuminate\Http\Request; -use Illuminate\Validation\ValidationException; -use PragmaRX\Google2FA\Exceptions\IncompatibleWithGoogleAuthenticatorException; -use PragmaRX\Google2FA\Exceptions\InvalidCharactersException; -use PragmaRX\Google2FA\Exceptions\SecretKeyTooShortException; -use PragmaRX\Google2FA\Google2FA; 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() { - // TODO - Redirect back to profile/edit if already setup? - // Show MFA setup route - return view('mfa.setup'); + $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. - * @throws IncompatibleWithGoogleAuthenticatorException - * @throws InvalidCharactersException - * @throws SecretKeyTooShortException + * Remove an MFA method for the current user. + * + * @throws \Exception */ - public function totpGenerate() + public function remove(string $method) { - // TODO - Ensure a QR code doesn't already exist? Or overwrite? - $google2fa = new Google2FA(); - if (session()->has(static::TOTP_SETUP_SECRET_SESSION_KEY)) { - $totpSecret = decrypt(session()->get(static::TOTP_SETUP_SECRET_SESSION_KEY)); - } else { - $totpSecret = $google2fa->generateSecretKey(); - 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 = $google2fa->getQRCodeUrl( - setting('app-name'), - user()->email, - $totpSecret - ); - - $color = Fill::uniformColor(new Rgb(255, 255, 255), new Rgb(32, 110, 167)); - $svg = (new Writer( - new ImageRenderer( - new RendererStyle(192, 0, null, null, $color), - new SvgImageBackEnd - ) - ))->writeString($qrCodeUrl); - - // Get user to verify setup via responding once. - // If correct response, Save key against user - 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) { - $this->validate($request, [ - 'code' => 'required|max:12|min:4' - ]); + $desiredMethod = $request->get('method'); + $userMethods = $this->currentOrLastAttemptedUser() + ->mfaValues() + ->get(['id', 'method']) + ->groupBy('method'); - // TODO - Confirm code - dd($request->input('code')); + // 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 view('mfa.verify', [ + 'userMethods' => $userMethods, + 'method' => $method, + 'otherMethods' => $otherMethods, + ]); } }