]> BookStack Code Mirror - bookstack/blobdiff - app/Http/Controllers/Auth/MfaController.php
Fixed failing test after drawio default url change
[bookstack] / app / Http / Controllers / Auth / MfaController.php
index 8ddccaa98cf3a18a58fd63bb52fd2d40645f7063..6f6beb873e4911c6a509450694550edbe98cc953 100644 (file)
@@ -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,
+        ]);
     }
 }