Passed
Push — master ( fd803f...bf0d13 )
by Darko
08:24
created

PasswordSecurityController::verify2fa()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 54
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
eloc 28
c 1
b 1
f 0
dl 0
loc 54
rs 9.1608
cc 5
nc 4
nop 1

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace App\Http\Controllers;
4
5
use App\Http\Requests\Disable2faPasswordSecurityRequest;
6
use App\Models\PasswordSecurity;
7
use Illuminate\Contracts\View\Factory;
8
use Illuminate\Contracts\View\View;
9
use Illuminate\Foundation\Application;
10
use Illuminate\Http\RedirectResponse;
11
use Illuminate\Http\Request;
12
use Illuminate\Support\Facades\Auth;
13
use Illuminate\Support\Facades\Hash;
14
15
class PasswordSecurityController extends Controller
16
{
17
    public function show2faForm(Request $request): Application|View|Factory|\Illuminate\Contracts\Foundation\Application
18
    {
19
        $user = $request->user();
20
21
        $google2fa_url = '';
22
        if ($user->passwordSecurity()->exists()) {
23
            $google2fa_url = \Google2FA::getQRCodeInline(
0 ignored issues
show
Bug introduced by
The type Google2FA was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
24
                config('app.name'),
25
                $user->email,
26
                $user->passwordSecurity->google2fa_secret
27
            );
28
        }
29
        $data = [
30
            'user' => $user,
31
            'google2fa_url' => $google2fa_url,
32
        ];
33
34
        return view('auth.2fa')->with('data', $data);
35
    }
36
37
    /**
38
     * @throws \PragmaRX\Google2FA\Exceptions\IncompatibleWithGoogleAuthenticatorException
39
     * @throws \PragmaRX\Google2FA\Exceptions\InvalidCharactersException
40
     * @throws \PragmaRX\Google2FA\Exceptions\SecretKeyTooShortException
41
     */
42
    public function generate2faSecret(Request $request): RedirectResponse
43
    {
44
        $user = $request->user();
45
46
        // Add the secret key to the registration data
47
        PasswordSecurity::create(
48
            [
49
                'user_id' => $user->id,
50
                'google2fa_enable' => 0,
51
                'google2fa_secret' => \Google2FA::generateSecretKey(),
52
            ]
53
        );
54
55
        return redirect()->to('2fa')->with('success', 'Secret Key is generated, Please verify Code to Enable 2FA');
56
    }
57
58
    /**
59
     * @throws \PragmaRX\Google2FA\Exceptions\IncompatibleWithGoogleAuthenticatorException
60
     * @throws \PragmaRX\Google2FA\Exceptions\InvalidCharactersException
61
     * @throws \PragmaRX\Google2FA\Exceptions\SecretKeyTooShortException
62
     */
63
    public function enable2fa(Request $request): RedirectResponse
64
    {
65
        $user = $request->user();
66
        $secret = $request->input('verify-code');
67
        $valid = \Google2FA::verifyKey($user->passwordSecurity->google2fa_secret, $secret);
68
        if ($valid) {
69
            $user->passwordSecurity->google2fa_enable = 1;
70
            $user->passwordSecurity->save();
71
72
            return redirect()->to('2fa')->with('success', '2FA is Enabled Successfully.');
73
        }
74
75
        return redirect()->to('2fa')->with('error', 'Invalid Verification Code, Please try again.');
76
    }
77
78
    public function disable2fa(Disable2faPasswordSecurityRequest $request): \Illuminate\Routing\Redirector|RedirectResponse|\Illuminate\Contracts\Foundation\Application
79
    {
80
        if (! (Hash::check($request->get('current-password'), $request->user()->password))) {
81
            // The passwords matches
82
            return redirect()->back()->with('error', 'Your password does not match with your account password. Please try again.');
83
        }
84
85
        $validatedData = $request->validated();
0 ignored issues
show
Unused Code introduced by
The assignment to $validatedData is dead and can be removed.
Loading history...
86
        $user = $request->user();
87
        $user->passwordSecurity->google2fa_enable = 0;
88
        $user->passwordSecurity->save();
89
90
        return redirect()->to('2fa')->with('success', '2FA is now Disabled.');
91
    }
92
93
    /**
94
     * Verify the 2FA code provided by the user.
95
     */
96
    public function verify2fa(Request $request): RedirectResponse
97
    {
98
        $request->validate([
99
            'one_time_password' => 'required|numeric',
100
        ]);
101
102
        // Get the user ID from session
103
        if (! $request->session()->has('2fa:user:id')) {
104
            return redirect()->route('login')
105
                ->with('message', 'The two-factor authentication session has expired. Please login again.')
106
                ->with('message_type', 'danger');
107
        }
108
109
        $userId = $request->session()->get('2fa:user:id');
110
        $user = \App\Models\User::find($userId);
111
112
        if (! $user || ! $user->passwordSecurity) {
113
            $request->session()->forget('2fa:user:id');
114
115
            return redirect()->route('login')
116
                ->with('message', 'User not found or 2FA not configured. Please login again.')
117
                ->with('message_type', 'danger');
118
        }
119
120
        // Verify the OTP code
121
        $valid = \Google2FA::verifyKey(
122
            $user->passwordSecurity->google2fa_secret,
123
            $request->input('one_time_password')
124
        );
125
126
        if (! $valid) {
127
            return redirect()->route('2fa.verify')
128
                ->with('message', 'Invalid authentication code. Please try again.')
129
                ->with('message_type', 'danger');
130
        }
131
132
        // Log the user back in
133
        Auth::login($user);
134
135
        // Mark the user as having passed 2FA
136
        session([config('google2fa.session_var') => true]);
137
138
        // Store the timestamp for determining how long the 2FA session is valid
139
        session([config('google2fa.session_var').'.auth.passed_at' => time()]);
140
141
        // Clean up the temporary session variable
142
        $request->session()->forget('2fa:user:id');
143
144
        // Determine where to redirect after successful verification
145
        $redirectUrl = $request->session()->pull('url.intended', '/');
146
147
        return redirect()->to($redirectUrl)
148
            ->with('message', 'Two-factor authentication verified successfully.')
149
            ->with('message_type', 'success');
150
    }
151
152
    /**
153
     * Display the 2FA verification form for a user who has already authenticated with username/password
154
     * but needs to enter their 2FA code.
155
     */
156
    public function getVerify2fa(Request $request)
157
    {
158
        // Check if user ID is stored in the session
159
        if (! $request->session()->has('2fa:user:id')) {
160
            return redirect()->route('login')
161
                ->withErrors(['msg' => 'The two-factor authentication session has expired. Please login again.']);
162
        }
163
164
        // Get the user ID from session
165
        $userId = $request->session()->get('2fa:user:id');
166
167
        // Get the user
168
        $user = \App\Models\User::find($userId);
169
        if (! $user) {
170
            $request->session()->forget('2fa:user:id');
171
172
            return redirect()->route('login')
173
                ->withErrors(['msg' => 'User not found. Please login again.']);
174
        }
175
176
        $theme = 'Gentele';
177
        $meta_title = 'Two Factor Authentication';
178
        $meta_keywords = 'Two Factor Authentication, 2FA';
179
        $meta_description = 'Two Factor Authentication Verification';
180
181
        app('smarty.view')->assign(compact('meta_title', 'meta_keywords', 'meta_description', 'user'));
182
183
        return app('smarty.view')->display($theme.'/2fa_verify.tpl');
184
    }
185
}
186