Completed
Push — develop ( e23518...79fd2e )
by Abdelrahman
02:07
created

AccountTwoFactorController::backupTotp()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 9
nc 1
nop 1
dl 0
loc 14
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Cortex\Fort\Http\Controllers\Frontarea;
6
7
use Illuminate\Http\Request;
8
use PragmaRX\Google2FA\Google2FA;
9
use Cortex\Foundation\Http\Controllers\AuthenticatedController;
10
use Cortex\Fort\Http\Requests\Frontarea\TwoFactorPhoneSettingsRequest;
11
use Cortex\Fort\Http\Requests\Frontarea\TwoFactorTotpBackupSettingsRequest;
12
use Cortex\Fort\Http\Requests\Frontarea\TwoFactorTotpProcessSettingsRequest;
13
14
class AccountTwoFactorController extends AuthenticatedController
15
{
16
    /**
17
     * Show the account security form.
18
     *
19
     * @param \Illuminate\Http\Request $request
20
     *
21
     * @return \Illuminate\View\View
22
     */
23
    public function index(Request $request)
24
    {
25
        $twoFactor = $request->user($this->getGuard())->getTwoFactor();
26
27
        return view('cortex/fort::frontarea.pages.account-twofactor', compact('twoFactor'));
28
    }
29
30
    /**
31
     * Enable TwoFactor TOTP authentication.
32
     *
33
     * @param \Illuminate\Http\Request      $request
34
     * @param \PragmaRX\Google2FA\Google2FA $totpProvider
35
     *
36
     * @return \Illuminate\View\View
37
     */
38
    public function enableTotp(Request $request, Google2FA $totpProvider)
39
    {
40
        $currentUser = $request->user($this->getGuard());
41
        $twoFactor = $currentUser->getTwoFactor();
42
43
        if (! $secret = array_get($twoFactor, 'totp.secret')) {
44
            $twoFactor['totp'] = [
45
                'enabled' => false,
46
                'secret' => $secret = $totpProvider->generateSecretKey(),
47
            ];
48
49
            $currentUser->fill(['two_factor' => $twoFactor])->forceSave();
50
        }
51
52
        $qrCode = $totpProvider->getQRCodeInline(config('app.name'), $currentUser->email, $secret);
53
54
        return view('cortex/fort::frontarea.pages.account-twofactor-totp', compact('secret', 'qrCode', 'twoFactor'));
55
    }
56
57
    /**
58
     * Disable TwoFactor TOTP authentication.
59
     *
60
     * @param \Illuminate\Http\Request $request
61
     *
62
     * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse
63
     */
64
    public function disableTotp(Request $request)
65
    {
66
        $currentUser = $request->user($this->getGuard());
67
        $twoFactor = $currentUser->getTwoFactor();
68
        $twoFactor['totp'] = [];
69
70
        $currentUser->fill(['two_factor' => $twoFactor])->forceSave();
71
72
        return intend([
73
            'back' => true,
74
            'with' => ['success' => trans('cortex/fort::messages.verification.twofactor.totp.disabled')],
75
        ]);
76
    }
77
78
    /**
79
     * Process the TwoFactor TOTP enable form.
80
     *
81
     * @param \Cortex\Fort\Http\Requests\Frontarea\TwoFactorTotpProcessSettingsRequest $request
82
     * @param \PragmaRX\Google2FA\Google2FA                                            $totpProvider
83
     *
84
     * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse
85
     */
86
    public function updateTotp(TwoFactorTotpProcessSettingsRequest $request, Google2FA $totpProvider)
87
    {
88
        $currentUser = $request->user($this->getGuard());
89
        $twoFactor = $currentUser->getTwoFactor();
90
        $secret = array_get($twoFactor, 'totp.secret');
91
        $backup = array_get($twoFactor, 'totp.backup');
92
        $backupAt = array_get($twoFactor, 'totp.backup_at');
93
94
        if ($totpProvider->verifyKey($secret, $request->get('token'))) {
95
            $twoFactor['totp'] = [
96
                'enabled' => true,
97
                'secret' => $secret,
98
                'backup' => $backup ?? $this->generateTotpBackups(),
99
                'backup_at' => $backupAt ?? now()->toDateTimeString(),
100
            ];
101
102
            // Update TwoFactor settings
103
            $currentUser->fill(['two_factor' => $twoFactor])->forceSave();
104
105
            return intend([
106
                'back' => true,
107
                'with' => ['success' => trans('cortex/fort::messages.verification.twofactor.totp.enabled')],
108
            ]);
109
        }
110
111
        return intend([
112
            'back' => true,
113
            'withErrors' => ['token' => trans('cortex/fort::messages.verification.twofactor.totp.invalid_token')],
114
        ]);
115
    }
116
117
    /**
118
     * Process the TwoFactor OTP backup.
119
     *
120
     * @param \Cortex\Fort\Http\Requests\Frontarea\TwoFactorTotpBackupSettingsRequest $request
121
     *
122
     * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse
123
     */
124
    public function backupTotp(TwoFactorTotpBackupSettingsRequest $request)
125
    {
126
        $currentUser = $request->user($this->getGuard());
127
        $twoFactor = $currentUser->getTwoFactor();
128
        $twoFactor['totp']['backup'] = $this->generateTotpBackups();
129
        $twoFactor['totp']['backup_at'] = now()->toDateTimeString();
130
131
        $currentUser->fill(['two_factor' => $twoFactor])->forceSave();
132
133
        return intend([
134
            'back' => true,
135
            'with' => ['success' => trans('cortex/fort::messages.verification.twofactor.totp.rebackup')],
136
        ]);
137
    }
138
139
    /**
140
     * Enable TwoFactor Phone authentication.
141
     *
142
     * @param \Cortex\Fort\Http\Requests\Frontarea\TwoFactorPhoneSettingsRequest $request
143
     *
144
     * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse
145
     */
146
    public function enablePhone(TwoFactorPhoneSettingsRequest $request)
147
    {
148
        $currentUser = $request->user($this->getGuard());
149
        $currentUser->routeNotificationForAuthy();
150
        $twoFactor = $currentUser->getTwoFactor();
151
        $twoFactor['phone']['enabled'] = true;
152
153
        $currentUser->fill(['two_factor' => $twoFactor])->forceSave();
154
155
        return intend([
156
            'back' => true,
157
            'with' => ['success' => trans('cortex/fort::messages.verification.twofactor.phone.enabled')],
158
        ]);
159
    }
160
161
    /**
162
     * Disable TwoFactor Phone authentication.
163
     *
164
     * @param \Illuminate\Http\Request $request
165
     *
166
     * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse
167
     */
168
    public function disablePhone(Request $request)
169
    {
170
        $currentUser = $request->user($this->getGuard());
171
        $twoFactor = $currentUser->getTwoFactor();
172
        $twoFactor['phone']['enabled'] = false;
173
174
        $currentUser->fill(['two_factor' => $twoFactor])->forceSave();
175
176
        return intend([
177
            'back' => true,
178
            'with' => ['success' => trans('cortex/fort::messages.verification.twofactor.phone.disabled')],
179
        ]);
180
    }
181
182
    /**
183
     * Generate TwoFactor OTP backup codes.
184
     *
185
     * @return array
186
     */
187
    protected function generateTotpBackups(): array
188
    {
189
        $backup = [];
190
191
        for ($x = 0; $x <= 9; $x++) {
192
            $backup[] = str_pad((string) random_int(0, 9999999999), 10, '0', STR_PAD_BOTH);
193
        }
194
195
        return $backup;
196
    }
197
}
198