GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( c4a10f...5fd32e )
by James
01:57
created

Google2FA::setQrCodeBackend()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 0
cts 3
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace PragmaRX\Google2FALaravel;
6
7
use Carbon\Carbon;
8
use Illuminate\Database\QueryException;
9
use Illuminate\Http\Request as IlluminateRequest;
10
use Illuminate\Support\Facades\DB;
11
use Illuminate\Support\Str;
12
use PragmaRX\Google2FALaravel\Events\LoggedOut;
13
use PragmaRX\Google2FALaravel\Events\OneTimePasswordExpired;
14
use PragmaRX\Google2FALaravel\Exceptions\InvalidSecretKey;
15
use PragmaRX\Google2FALaravel\Support\Auth;
16
use PragmaRX\Google2FALaravel\Support\Config;
17
use PragmaRX\Google2FALaravel\Support\Constants;
18
use PragmaRX\Google2FALaravel\Support\Request;
19
use PragmaRX\Google2FALaravel\Support\Session;
20
use PragmaRX\Google2FAQRCode\Google2FA as Google2FAService;
21
22
/**
23
 * Class Google2FA
24
 */
25
class Google2FA extends Google2FAService
26
{
27
    use Auth, Config, Request, Session;
28
29
    protected $qrCodeBackend;
30
31
    /**
32
     * Construct the correct backend.
33
     */
34 4
    protected function constructBackend(): void
35
    {
36 4
        switch ($this->getQRCodeBackend()) {
37 4
            case Constants::QRCODE_IMAGE_BACKEND_SVG:
38
                parent::__construct(new \BaconQrCode\Renderer\Image\SvgImageBackEnd());
39
                break;
40
41 4
            case Constants::QRCODE_IMAGE_BACKEND_EPS:
42
                parent::__construct(new \BaconQrCode\Renderer\Image\EpsImageBackEnd());
43
                break;
44
45 4
            case Constants::QRCODE_IMAGE_BACKEND_IMAGEMAGICK:
46
            default:
47 4
                parent::__construct();
48 4
                break;
49
        }
50 4
    }
51
52
    /**
53
     * Set the QRCode Backend.
54
     *
55
     * @param string $qrCodeBackend
56
     *
57
     * @return self
58
     */
59
    public function setQrCodeBackend(string $qrCodeBackend)
60
    {
61
        $this->qrCodeBackend = $qrCodeBackend;
62
63
        return $this;
64
    }
65
66
    /**
67
     * Authenticator constructor.
68
     *
69
     * @param IlluminateRequest $request
70
     */
71 4
    public function __construct(IlluminateRequest $request)
72
    {
73 4
        $this->boot($request);
74
75 4
        $this->constructBackend();
76 4
    }
77
78
    /**
79
     * Authenticator boot.
80
     *
81
     * @param $request
82
     *
83
     * @return Google2FA
84
     */
85 4
    public function boot($request)
86
    {
87 4
        $this->setRequest($request);
88
89 4
        return $this;
90
    }
91
92
    /**
93
     * The QRCode Backend.
94
     *
95
     * @return mixed
96
     */
97 4
    public function getQRCodeBackend()
98
    {
99 4
        return $this->qrCodeBackend
100 4
            ?: $this->config('qrcode_image_backend', Constants::QRCODE_IMAGE_BACKEND_IMAGEMAGICK);
101
    }
102
103
    /**
104
     * Get the user Google2FA secret.
105
     *
106
     * @throws InvalidSecretKey
107
     *
108
     * @return mixed
109
     */
110 2
    protected function getGoogle2FASecretKey()
111
    {
112 2
        return $this->getUser()->{$this->config('otp_secret_column')};
113
    }
114
115
    /**
116
     * Check if the 2FA is activated for the user.
117
     *
118
     * @return bool
119
     */
120 2
    public function isActivated()
121
    {
122 2
        $secret = $this->getGoogle2FASecretKey();
123
124 2
        return !is_null($secret) && !empty($secret);
125
    }
126
127
    /**
128
     * Store the old OTP timestamp.
129
     *
130
     * @param $key
131
     *
132
     * @return mixed
133
     */
134
    protected function storeOldTimestamp($key)
135
    {
136
        return $this->config('forbid_old_passwords') === true
137
            ? $this->sessionPut(Constants::SESSION_OTP_TIMESTAMP, $key)
138
            : $key;
139
    }
140
141
    /**
142
     * Get the previous OTP timestamp.
143
     *
144
     * @return null|mixed
145
     */
146 1
    protected function getOldTimestamp()
147
    {
148 1
        return $this->config('forbid_old_passwords') === true
149
            ? $this->sessionGet(Constants::SESSION_OTP_TIMESTAMP)
150 1
            : null;
151
    }
152
153
    /**
154
     * Keep this OTP session alive.
155
     */
156
    protected function keepAlive()
157
    {
158
        if ($this->config('keep_alive')) {
159
            $this->updateCurrentAuthTime();
160
        }
161
    }
162
163
    /**
164
     * Get minutes since last activity.
165
     *
166
     * @return int
167
     */
168
    protected function minutesSinceLastActivity()
169
    {
170
        return Carbon::now()->diffInMinutes(
171
            $this->sessionGet(Constants::SESSION_AUTH_TIME)
172
        );
173
    }
174
175
    /**
176
     * Check if no user is authenticated using OTP.
177
     *
178
     * @return bool
179
     */
180 1
    protected function noUserIsAuthenticated()
181
    {
182 1
        return is_null($this->getUser());
183
    }
184
185
    /**
186
     * Check if OTP has expired.
187
     *
188
     * @return bool
189
     */
190
    protected function passwordExpired()
191
    {
192
        if (($minutes = $this->config('lifetime')) !== 0 && $this->minutesSinceLastActivity() > $minutes) {
193
            event(new OneTimePasswordExpired($this->getUser()));
194
195
            $this->logout();
196
197
            return true;
198
        }
199
200
        $this->keepAlive();
201
202
        return false;
203
    }
204
205
    /**
206
     * Verifies, in the current session, if a 2fa check has already passed.
207
     *
208
     * @return bool
209
     */
210 1
    protected function twoFactorAuthStillValid()
211
    {
212
        return
213 1
            (bool) $this->sessionGet(Constants::SESSION_AUTH_PASSED, false) &&
214 1
            !$this->passwordExpired();
215
    }
216
217
    /**
218
     * Check if the module is enabled.
219
     *
220
     * @return mixed
221
     */
222 1
    protected function isEnabled()
223
    {
224 1
        return $this->config('enabled');
225
    }
226
227
    /**
228
     * Set current auth as valid.
229
     */
230
    public function login()
231
    {
232
        $this->sessionPut(Constants::SESSION_AUTH_PASSED, true);
233
        $this->updateCurrentAuthTime();
234
        $this->generateCookieToken();
235
236
    }
237
238
    /**
239
     * OTP logout.
240
     */
241
    public function logout()
242
    {
243
        $user = $this->getUser();
244
245
        $this->sessionForget();
246
247
        event(new LoggedOut($user));
248
    }
249
250
    /**
251
     * Update the current auth time.
252
     */
253
    protected function updateCurrentAuthTime()
254
    {
255
        $this->sessionPut(Constants::SESSION_AUTH_TIME, Carbon::now());
256
    }
257
258
    /**
259
     * Verify the OTP.
260
     *
261
     * @param $secret
262
     * @param $one_time_password
263
     *
264
     * @return mixed
265
     */
266 1
    public function verifyGoogle2FA($secret, $one_time_password)
267
    {
268 1
        return $this->verifyKey(
269 1
                $secret,
270
                $one_time_password,
271 1
                $this->config('window'),
272 1
                null, // $timestamp
273 1
                $this->getOldTimestamp() ?: null
274
        );
275
    }
276
277
    /**
278
     * Verify the OTP and store the timestamp.
279
     *
280
     * @param $one_time_password
281
     *
282
     * @return mixed
283
     */
284
    protected function verifyAndStoreOneTimePassword($one_time_password)
285
    {
286
        return $this->storeOldTimeStamp(
287
            $this->verifyGoogle2FA(
288
                $this->getGoogle2FASecretKey(),
289
                $one_time_password
290
            )
291
        );
292
    }
293
294
    /**
295
     * Generate token, store in session.
296
     */
297
    private function generateCookieToken(): void
298
    {
299
        if (true === $this->config('store_in_cookie')) {
300
            // generate token and store in DB.
301
            // loop to prevent duplicates (you never know)
302
            $loops  = 0;
303
            $token  = null;
304
            $unique = false;
305
            $user   = $this->getUser();
306
            $expire = time() + (int)$this->config('cookie_lifetime');
307
            while ($loops < 10 && false === $unique) {
308
                $token = Str::random(64);
309
                try {
310
                    // store token in DB
311
                    DB::table('2fa_tokens')->insert(
312
                        [
313
                            'user_id'    => $user->id,
314
                            'expires_at' => date('Y-m-d H:i:s', $expire),
315
                            'token'      => $token,
316
                        ]
317
                    );
318
                } catch (QueryException $e) {
319
                    // token exists or DB error. Try again.
320
                    $loops++;
321
                    continue;
322
                }
323
                // break loop.
324
                $loops  = 20;
325
                $unique = true;
326
            }
327
            if (null !== $token) {
328
                $this->sessionPut(Constants::SESSION_TOKEN, $token);
329
            }
330
        }
331
    }
332
}
333