]> BookStack Code Mirror - bookstack/blob - app/Http/Controllers/Auth/MfaController.php
Added TOTP generation view and started verification stage
[bookstack] / app / Http / Controllers / Auth / MfaController.php
1 <?php
2
3 namespace BookStack\Http\Controllers\Auth;
4
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;
18
19 class MfaController extends Controller
20 {
21     protected const TOTP_SETUP_SECRET_SESSION_KEY = 'mfa-setup-totp-secret';
22
23     /**
24      * Show the view to setup MFA for the current user.
25      */
26     public function setup()
27     {
28         // TODO - Redirect back to profile/edit if already setup?
29         // Show MFA setup route
30         return view('mfa.setup');
31     }
32
33     /**
34      * Show a view that generates and displays a TOTP QR code.
35      * @throws IncompatibleWithGoogleAuthenticatorException
36      * @throws InvalidCharactersException
37      * @throws SecretKeyTooShortException
38      */
39     public function totpGenerate()
40     {
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));
45         } else {
46             $totpSecret = $google2fa->generateSecretKey();
47             session()->put(static::TOTP_SETUP_SECRET_SESSION_KEY, encrypt($totpSecret));
48         }
49
50         $qrCodeUrl = $google2fa->getQRCodeUrl(
51             setting('app-name'),
52             user()->email,
53             $totpSecret
54         );
55
56         $color = Fill::uniformColor(new Rgb(255, 255, 255), new Rgb(32, 110, 167));
57         $svg = (new Writer(
58             new ImageRenderer(
59                 new RendererStyle(192, 0, null, null, $color),
60                 new SvgImageBackEnd
61             )
62         ))->writeString($qrCodeUrl);
63
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,
68             'svg' => $svg,
69         ]);
70     }
71
72     /**
73      * Confirm the setup of TOTP and save the auth method secret
74      * against the current user.
75      * @throws ValidationException
76      */
77     public function totpConfirm(Request $request)
78     {
79         $this->validate($request, [
80             'code' => 'required|max:12|min:4'
81         ]);
82
83         // TODO - Confirm code
84         dd($request->input('code'));
85     }
86 }