Completed
Push — develop ( d878ad...d28e4b )
by Abdelrahman
05:14
created

TwoFactorAuthenticatesUsers   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 85
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
dl 0
loc 85
rs 10
c 0
b 0
f 0
wmc 12
lcom 1
cbo 1

5 Methods

Rating   Name   Duplication   Size   Complexity  
A attemptTwoFactor() 0 4 3
A invalidateTwoFactorBackup() 0 12 1
A isValidTwoFactorPhone() 0 7 2
A isValidTwoFactorBackup() 0 8 3
A isValidTwoFactorTotp() 0 7 3
1
<?php
2
3
namespace Cortex\Fort\Traits;
4
5
use PragmaRX\Google2FA\Google2FA;
6
use Rinvex\Fort\Contracts\AuthenticatableTwoFactorContract;
7
8
trait TwoFactorAuthenticatesUsers
9
{
10
    /**
11
     * Verify TwoFactor authentication.
12
     *
13
     * @param \Rinvex\Fort\Contracts\AuthenticatableTwoFactorContract $user
14
     * @param int                                                     $token
15
     *
16
     * @return bool
17
     */
18
    protected function attemptTwoFactor(AuthenticatableTwoFactorContract $user, int $token): bool
19
    {
20
        return $this->isValidTwoFactorTotp($user, $token) || $this->isValidTwoFactorBackup($user, $token) || $this->isValidTwoFactorPhone($user, $token);
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 153 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
21
    }
22
23
    /**
24
     * Invalidate given backup code for the given user.
25
     *
26
     * @param \Rinvex\Fort\Contracts\AuthenticatableTwoFactorContract $user
27
     * @param int                                                     $token
28
     *
29
     * @return void
30
     */
31
    protected function invalidateTwoFactorBackup(AuthenticatableTwoFactorContract $user, int $token): void
32
    {
33
        $settings = $user->getTwoFactor();
34
        $backup = array_get($settings, 'totp.backup');
0 ignored issues
show
Bug introduced by
It seems like $settings defined by $user->getTwoFactor() on line 33 can also be of type null; however, array_get() does only seem to accept object<ArrayAccess>|array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
35
36
        unset($backup[array_search($token, $backup)]);
37
38
        array_set($settings, 'totp.backup', $backup);
0 ignored issues
show
Bug introduced by
It seems like $settings defined by $user->getTwoFactor() on line 33 can also be of type null; however, array_set() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
39
40
        // Update TwoFactor OTP backup codes
41
        $user->fill(['two_factor' => $settings])->forceSave();
42
    }
43
44
    /**
45
     * Determine if the given token is a valid TwoFactor Phone token.
46
     *
47
     * @param \Rinvex\Fort\Contracts\AuthenticatableTwoFactorContract $user
48
     * @param int                                                     $token
49
     *
50
     * @return bool
51
     */
52
    protected function isValidTwoFactorPhone(AuthenticatableTwoFactorContract $user, int $token): bool
53
    {
54
        $settings = $user->getTwoFactor();
55
        $authyId = array_get($settings, 'phone.authy_id');
0 ignored issues
show
Bug introduced by
It seems like $settings defined by $user->getTwoFactor() on line 54 can also be of type null; however, array_get() does only seem to accept object<ArrayAccess>|array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
56
57
        return in_array(mb_strlen($token), [6, 7, 8]) && app('rinvex.authy.token')->verify($token, $authyId)->succeed();
58
    }
59
60
    /**
61
     * Determine if the given token is a valid TwoFactor Backup code.
62
     *
63
     * @param \Rinvex\Fort\Contracts\AuthenticatableTwoFactorContract $user
64
     * @param int                                                     $token
65
     *
66
     * @return bool
67
     */
68
    protected function isValidTwoFactorBackup(AuthenticatableTwoFactorContract $user, int $token): bool
69
    {
70
        $backup = array_get($user->getTwoFactor(), 'totp.backup', []);
0 ignored issues
show
Bug introduced by
It seems like $user->getTwoFactor() targeting Rinvex\Fort\Contracts\Au...ontract::getTwoFactor() can also be of type null; however, array_get() does only seem to accept object<ArrayAccess>|array, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
71
        $result = mb_strlen($token) === 10 && in_array($token, $backup);
72
        ! $result || $this->invalidateTwoFactorBackup($user, $token);
73
74
        return $result;
75
    }
76
77
    /**
78
     * Determine if the given token is a valid TwoFactor TOTP token.
79
     *
80
     * @param \Rinvex\Fort\Contracts\AuthenticatableTwoFactorContract $user
81
     * @param int                                                     $token
82
     *
83
     * @return bool
84
     */
85
    protected function isValidTwoFactorTotp(AuthenticatableTwoFactorContract $user, int $token): bool
86
    {
87
        $totpProvider = app(Google2FA::class);
88
        $secret = array_get($user->getTwoFactor(), 'totp.secret');
0 ignored issues
show
Bug introduced by
It seems like $user->getTwoFactor() targeting Rinvex\Fort\Contracts\Au...ontract::getTwoFactor() can also be of type null; however, array_get() does only seem to accept object<ArrayAccess>|array, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
89
90
        return mb_strlen($token) === 6 && request()->session()->get('rinvex.fort.twofactor.totp') && $totpProvider->verifyKey($secret, $token);
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 143 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
91
    }
92
}
93