Completed
Pull Request — master (#18)
by
unknown
20:30 queued 06:19
created

Authenticator::storeOldOneTimePassord()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
namespace PragmaRX\Google2FALaravel\Support;
4
5
use Carbon\Carbon;
6
use Google2FA;
7
use Illuminate\Http\Request as IlluminateRequest;
8
use PragmaRX\Google2FA\Support\Constants as Google2FAConstants;
9
use PragmaRX\Google2FALaravel\Exceptions\InvalidSecretKey;
10
11
class Authenticator
12
{
13
    use Auth, Config, Request, Session;
14
15
    /**
16
     * Authenticator constructor.
17
     *
18
     * @param IlluminateRequest $request
19
     */
20
    public function __construct(IlluminateRequest $request)
21
    {
22
        $this->boot($request);
23
    }
24
25
    /**
26
     * Authenticator boot.
27
     *
28
     * @param $request
29
     *
30
     * @return Authenticator
31
     */
32
    public function boot($request)
33
    {
34
        $this->setRequest($request);
35
36
        return $this;
37
    }
38
39
    /**
40
     * Check if it is already logged in or passable without checking for an OTP.
41
     *
42
     * @return bool
43
     */
44
    protected function canPassWithoutCheckingOTP()
45
    {
46
        return
47
            !$this->isEnabled() ||
48
            $this->noUserIsAuthenticated() ||
49
            !$this->isActivated() ||
50
            $this->twoFactorAuthStillValid();
51
    }
52
53
    /**
54
     * Get the user Google2FA secret.
55
     *
56
     * @throws InvalidSecretKey
57
     *
58
     * @return mixed
59
     */
60
    protected function getGoogle2FASecretKey()
61
    {
62
        return $this->getUser()->{$this->config('otp_secret_column')};
63
    }
64
65
    /**
66
     * Check if the 2FA is activated for the user.
67
     *
68
     * @return bool
69
     */
70
    public function isActivated()
71
    {
72
        $secret = $this->getGoogle2FASecretKey();
73
74
        return !is_null($secret) && !empty($secret);
75
    }
76
77
    /**
78
     * Store the old OTP timestamp.
79
     *
80
     * @param $key
81
     *
82
     * @return mixed
83
     */
84
    protected function storeOldTimestamp($key)
85
    {
86
        return $this->config('forbid_old_passwords') === true
87
            ? $this->sessionPut(Constants::SESSION_OTP_TIMESTAMP, $key)
88
            : $key;
89
    }
90
91
    /**
92
     * Get the previous OTP timestamp.
93
     *
94
     * @return null|void
95
     */
96
    protected function getOldTimestamp()
97
    {
98
        return $this->config('forbid_old_passwords') === true
99
            ? $this->sessionGet(Constants::SESSION_OTP_TIMESTAMP)
100
            : null;
101
    }
102
103
    /**
104
     * Keep this OTP session alive.
105
     */
106
    protected function keepAlive()
107
    {
108
        if ($this->config('keep_alive')) {
109
            $this->updateCurrentAuthTime();
110
        }
111
    }
112
113
    /**
114
     * Get minutes since last activity.
115
     *
116
     * @return int
117
     */
118
    protected function minutesSinceLastActivity()
119
    {
120
        return Carbon::now()->diffInMinutes(
121
            $this->sessionGet(Constants::SESSION_AUTH_TIME)
122
        );
123
    }
124
125
    /**
126
     * Check if no user is authenticated using OTP.
127
     *
128
     * @return bool
129
     */
130
    protected function noUserIsAuthenticated()
131
    {
132
        return is_null($this->getUser());
133
    }
134
135
    /**
136
     * Check if OTP has expired.
137
     *
138
     * @return bool
139
     */
140
    protected function passwordExpired()
141
    {
142
        if (($minutes = $this->config('lifetime')) !== 0 && $this->minutesSinceLastActivity() > $minutes) {
143
            $this->logout();
144
145
            return true;
146
        }
147
148
        $this->keepAlive();
149
150
        return false;
151
    }
152
153
    /**
154
     * Verifies, in the current session, if a 2fa check has already passed.
155
     *
156
     * @return bool
157
     */
158
    protected function twoFactorAuthStillValid()
159
    {
160
        return
161
            (bool) $this->sessionGet(Constants::SESSION_AUTH_PASSED, false) &&
162
            !$this->passwordExpired();
163
    }
164
165
    /**
166
     * Check if the module is enabled.
167
     *
168
     * @return mixed
169
     */
170
    protected function isEnabled()
171
    {
172
        return $this->config('enabled');
173
    }
174
175
    /**
176
     * Set current auth as valid.
177
     */
178
    public function login()
179
    {
180
        $this->sessionPut(Constants::SESSION_AUTH_PASSED, true);
181
182
        $this->updateCurrentAuthTime();
183
    }
184
185
    /**
186
     * OTP logout.
187
     */
188
    public function logout()
189
    {
190
        $this->sessionForget();
191
    }
192
193
    /**
194
     * Update the current auth time.
195
     */
196
    protected function updateCurrentAuthTime()
197
    {
198
        $this->sessionPut(Constants::SESSION_AUTH_TIME, Carbon::now());
199
    }
200
201
    /**
202
     * Verify the OTP.
203
     *
204
     * @return mixed
205
     */
206
    public function verifyGoogle2FA($secret, $one_time_password)
207
    {
208
        return Google2Fa::verifyKey(
209
                $secret,
210
                $one_time_password,
211
                $this->config('window'),
212
                null, // $timestamp
213
                $this->getOldTimestamp() ?: Google2FAConstants::ARGUMENT_NOT_SET
214
        );
215
    }
216
217
    /**
218
     * Verify the OTP and store the timestamp.
219
     *
220
     * @return mixed
221
     */
222
    protected function verifyAndStoreOneTimePassord($one_time_password)
223
    {
224
        return $this->storeOldTimeStamp(
225
            $this->verifyGoogle2FA(
226
                $this->getGoogle2FASecretKey(),
227
                $one_time_password
228
            )
229
        );
230
    }
231
}
232