]> BookStack Code Mirror - bookstack/blobdiff - app/Http/Controllers/Auth/MfaController.php
Adjusted global search preview for dark mode
[bookstack] / app / Http / Controllers / Auth / MfaController.php
index be381e3b0d5e23271e6b030ab911e3ce97e2fbb6..6f6beb873e4911c6a509450694550edbe98cc953 100644 (file)
@@ -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,
+        ]);
     }
 }