Completed
Pull Request — master (#81)
by
unknown
01:39
created

Google2FA::updateCurrentAuthTime()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 4
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace PragmaRX\Google2FALaravel;
4
5
use Carbon\Carbon;
6
use Illuminate\Http\Request as IlluminateRequest;
7
use PragmaRX\Google2FA\Support\Constants as Google2FAConstants;
8
use PragmaRX\Google2FALaravel\Events\LoggedOut;
9
use PragmaRX\Google2FALaravel\Events\OneTimePasswordExpired;
10
use PragmaRX\Google2FALaravel\Exceptions\InvalidSecretKey;
11
use PragmaRX\Google2FALaravel\Support\Auth;
12
use PragmaRX\Google2FALaravel\Support\Config;
13
use PragmaRX\Google2FALaravel\Support\Constants;
14
use PragmaRX\Google2FALaravel\Support\Request;
15
use PragmaRX\Google2FALaravel\Support\Session;
16
use PragmaRX\Google2FAQRCode\Google2FA as Google2FAService;
17
18
class Google2FA extends Google2FAService
19
{
20
    use Auth, Config, Request, Session;
21
22
    protected $qrCodeBackend;
23
24
    /**
25
     * Construct the correct backend.
26
     */
27 14
    protected function constructBackend(): void
28
    {
29 14
        switch ($this->getQRCodeBackend()) {
30 14
            case Constants::QRCODE_IMAGE_BACKEND_SVG:
31
                parent::__construct(new \BaconQrCode\Renderer\Image\SvgImageBackEnd());
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (__construct() instead of constructBackend()). Are you sure this is correct? If so, you might want to change this to $this->__construct().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
32
                break;
33
34 14
            case Constants::QRCODE_IMAGE_BACKEND_EPS:
35
                parent::__construct(new \BaconQrCode\Renderer\Image\EpsImageBackEnd());
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (__construct() instead of constructBackend()). Are you sure this is correct? If so, you might want to change this to $this->__construct().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
36
                break;
37
38 14
            case Constants::QRCODE_IMAGE_BACKEND_IMAGEMAGICK:
39
            default:
40 14
                parent::__construct();
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (__construct() instead of constructBackend()). Are you sure this is correct? If so, you might want to change this to $this->__construct().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
41 14
                break;
42
        }
43 14
    }
44
45
    /**
46
     * Set the QRCode Backend.
47
     *
48
     * @param string $qrCodeBackend
49
     *
50
     * @return self
51
     */
52
    public function setQrCodeBackend(string $qrCodeBackend)
53
    {
54
        $this->qrCodeBackend = $qrCodeBackend;
55
56
        return $this;
57
    }
58
59
    /**
60
     * Authenticator constructor.
61
     *
62
     * @param IlluminateRequest $request
63
     */
64 14
    public function __construct(IlluminateRequest $request)
65
    {
66 14
        $this->boot($request);
67
68 14
        $this->constructBackend();
69 14
    }
70
71
    /**
72
     * Authenticator boot.
73
     *
74
     * @param $request
75
     *
76
     * @return Google2FA
77
     */
78 14
    public function boot($request)
79
    {
80 14
        $this->setRequest($request);
81
82 14
        return $this;
83
    }
84
85
    /**
86
     * The QRCode Backend.
87
     *
88
     * @return mixed
89
     */
90 14
    public function getQRCodeBackend()
91
    {
92 14
        return $this->qrCodeBackend
93 14
            ?: $this->config('qrcode_image_backend', Constants::QRCODE_IMAGE_BACKEND_IMAGEMAGICK);
94
    }
95
96
    /**
97
     * Get the user Google2FA secret.
98
     *
99
     * @throws InvalidSecretKey
100
     *
101
     * @return mixed
102
     */
103 10
    protected function getGoogle2FASecretKey()
104
    {
105 10
        return $this->getUser()->{$this->config('otp_secret_column')};
106
    }
107
108
    /**
109
     * Check if the 2FA is activated for the user.
110
     *
111
     * @return bool
112
     */
113 10
    public function isActivated()
114
    {
115 10
        $secret = $this->getGoogle2FASecretKey();
116
117 10
        return !is_null($secret) && !empty($secret);
118
    }
119
120
    /**
121
     * Store the old OTP timestamp.
122
     *
123
     * @param $key
124
     *
125
     * @return mixed
126
     */
127 5
    protected function storeOldTimestamp($key)
128
    {
129 5
        return $this->config('forbid_old_passwords') === true
130 1
            ? $this->sessionPut(Constants::SESSION_OTP_TIMESTAMP, $key)
131 5
            : $key;
132
    }
133
134
    /**
135
     * Get the previous OTP timestamp.
136
     *
137
     * @return null|mixed
138
     */
139 6
    protected function getOldTimestamp()
140
    {
141 6
        return $this->config('forbid_old_passwords') === true
142 1
            ? $this->sessionGet(Constants::SESSION_OTP_TIMESTAMP)
143 6
            : null;
144
    }
145
146
    /**
147
     * Keep this OTP session alive.
148
     */
149 4
    protected function keepAlive()
150
    {
151 4
        if ($this->config('keep_alive')) {
152 4
            $this->updateCurrentAuthTime();
153
        }
154 4
    }
155
156
    /**
157
     * Get minutes since last activity.
158
     *
159
     * @return int
160
     */
161 1
    protected function minutesSinceLastActivity()
162
    {
163 1
        return Carbon::now()->diffInMinutes(
164 1
            $this->sessionGet(Constants::SESSION_AUTH_TIME)
165
        );
166
    }
167
168
    /**
169
     * Check if no user is authenticated using OTP.
170
     *
171
     * @return bool
172
     */
173 9
    protected function noUserIsAuthenticated()
174
    {
175 9
        return is_null($this->getUser());
176
    }
177
178
    /**
179
     * Check if OTP has expired.
180
     *
181
     * @return bool
182
     */
183 4
    protected function passwordExpired()
184
    {
185 4
        if (($minutes = $this->config('lifetime')) !== 0 && $this->minutesSinceLastActivity() > $minutes) {
186 1
            event(new OneTimePasswordExpired($this->getUser()));
187
188 1
            $this->logout();
189
190 1
            return true;
191
        }
192
193 4
        $this->keepAlive();
194
195 4
        return false;
196
    }
197
198
    /**
199
     * Verifies, in the current session, if a 2fa check has already passed.
200
     *
201
     * @return bool
202
     */
203 9
    protected function twoFactorAuthStillValid()
204
    {
205
        return
206 9
            (bool) $this->sessionGet(Constants::SESSION_AUTH_PASSED, false) &&
207 9
            !$this->passwordExpired();
208
    }
209
210
    /**
211
     * Check if the module is enabled.
212
     *
213
     * @return mixed
214
     */
215 9
    protected function isEnabled()
216
    {
217 9
        return $this->config('enabled');
218
    }
219
220
    /**
221
     * Set current auth as valid.
222
     */
223 5
    public function login()
224
    {
225 5
        $this->sessionPut(Constants::SESSION_AUTH_PASSED, true);
226
227 5
        $this->updateCurrentAuthTime();
228 5
    }
229
230
    /**
231
     * OTP logout.
232
     */
233 3
    public function logout()
234
    {
235 3
        $user = $this->getUser();
236
237 3
        $this->sessionForget();
238
239 3
        event(new LoggedOut($user));
240 3
    }
241
242
    /**
243
     * Update the current auth time.
244
     */
245 5
    protected function updateCurrentAuthTime()
246
    {
247 5
        $this->sessionPut(Constants::SESSION_AUTH_TIME, Carbon::now());
248 5
    }
249
250
    /**
251
     * Verify the OTP.
252
     *
253
     * @param $secret
254
     * @param $one_time_password
255
     *
256
     * @return mixed
257
     */
258 6
    public function verifyGoogle2FA($secret, $one_time_password)
259
    {
260 6
        return $this->verifyKey(
261 6
                $secret,
262
                $one_time_password,
263 6
                $this->config('window'),
264 6
                null, // $timestamp
265 6
                $this->getOldTimestamp() ?: Google2FAConstants::ARGUMENT_NOT_SET
266
        );
267
    }
268
269
    /**
270
     * Verify the OTP and store the timestamp.
271
     *
272
     * @param $one_time_password
273
     *
274
     * @return mixed
275
     */
276 5
    protected function verifyAndStoreOneTimePassword($one_time_password)
277
    {
278 5
        return $this->storeOldTimeStamp(
279 5
            $this->verifyGoogle2FA(
280 5
                $this->getGoogle2FASecretKey(),
281
                $one_time_password
282
            )
283
        );
284
    }
285
}
286