3 namespace BookStack\Http\Controllers\Auth;
5 use BaconQrCode\Renderer\Color\Rgb;
6 use BaconQrCode\Renderer\Image\SvgImageBackEnd;
7 use BaconQrCode\Renderer\ImageRenderer;
8 use BaconQrCode\Renderer\RendererStyle\Fill;
9 use BaconQrCode\Renderer\RendererStyle\RendererStyle;
10 use BaconQrCode\Writer;
11 use BookStack\Http\Controllers\Controller;
12 use Illuminate\Http\Request;
13 use Illuminate\Validation\ValidationException;
14 use PragmaRX\Google2FA\Exceptions\IncompatibleWithGoogleAuthenticatorException;
15 use PragmaRX\Google2FA\Exceptions\InvalidCharactersException;
16 use PragmaRX\Google2FA\Exceptions\SecretKeyTooShortException;
17 use PragmaRX\Google2FA\Google2FA;
19 class MfaController extends Controller
21 protected const TOTP_SETUP_SECRET_SESSION_KEY = 'mfa-setup-totp-secret';
24 * Show the view to setup MFA for the current user.
26 public function setup()
28 // TODO - Redirect back to profile/edit if already setup?
29 // Show MFA setup route
30 return view('mfa.setup');
34 * Show a view that generates and displays a TOTP QR code.
35 * @throws IncompatibleWithGoogleAuthenticatorException
36 * @throws InvalidCharactersException
37 * @throws SecretKeyTooShortException
39 public function totpGenerate()
41 // TODO - Ensure a QR code doesn't already exist? Or overwrite?
42 $google2fa = new Google2FA();
43 if (session()->has(static::TOTP_SETUP_SECRET_SESSION_KEY)) {
44 $totpSecret = decrypt(session()->get(static::TOTP_SETUP_SECRET_SESSION_KEY));
46 $totpSecret = $google2fa->generateSecretKey();
47 session()->put(static::TOTP_SETUP_SECRET_SESSION_KEY, encrypt($totpSecret));
50 $qrCodeUrl = $google2fa->getQRCodeUrl(
56 $color = Fill::uniformColor(new Rgb(255, 255, 255), new Rgb(32, 110, 167));
59 new RendererStyle(192, 0, null, null, $color),
62 ))->writeString($qrCodeUrl);
64 // Get user to verify setup via responding once.
65 // If correct response, Save key against user
66 return view('mfa.totp-generate', [
67 'secret' => $totpSecret,
73 * Confirm the setup of TOTP and save the auth method secret
74 * against the current user.
75 * @throws ValidationException
77 public function totpConfirm(Request $request)
79 $this->validate($request, [
80 'code' => 'required|max:12|min:4'
83 // TODO - Confirm code
84 dd($request->input('code'));