Passed
Push — master ( 77e960...4a42e0 )
by Alexis
02:01
created

src/Security/Jwt/Manager.php (1 issue)

Labels
Severity
1
<?php
2
3
namespace App\Security\Jwt;
4
5
use App\Security\Model\AccessToken;
6
use App\Security\Model\RefreshToken;
7
use App\Security\Model\User;
8
use Firebase\JWT\ExpiredException;
9
use Firebase\JWT\JWT;
10
use Illuminate\Database\QueryException;
11
12
class Manager
13
{
14
    const ACCESS_TOKEN_LIFETIME = 3600;
15
    const REFRESH_TOKEN_LIFETIME = 1209600;
16
17
    /**
18
     * @var string
19
     */
20
    private $secret;
21
22
    /**
23
     * @var int
24
     */
25
    private $accessTokenLifetime;
26
27
    /**
28
     * @var int
29
     */
30
    private $refreshTokenLifetime;
31
32
    /**
33
     * @var string
34
     */
35
    private $serverName;
36
37
    /**
38
     * @var AccessToken
39
     */
40
    private $accessToken;
41
42
    /**
43
     * Constructor.
44
     *
45
     * @param string $secret
46
     * @param array  $config
47
     */
48
    public function __construct($secret, array $config = [])
49
    {
50
        $this->secret = $secret;
51
52
        $this->accessTokenLifetime = isset($config['access_token_lifetime']) ? $config['access_token_lifetime'] : self::ACCESS_TOKEN_LIFETIME;
53
        $this->refreshTokenLifetime = isset($config['refresh_token_lifetime']) ? $config['refresh_token_lifetime'] : self::REFRESH_TOKEN_LIFETIME;
54
        $this->serverName = isset($config['server_name']) ? $config['server_name'] : '';
55
    }
56
57
    /**
58
     * Checks if an Access Token is valid.
59
     *
60
     * @param string $token
61
     *
62
     * @return bool
63
     */
64 View Code Duplication
    public function checkAccessToken($token)
65
    {
66
        $accessToken = AccessToken::with('user')->where('token', $token)->first();
67
68
        if (null === $accessToken) {
69
            return false;
70
        }
71
72
        try {
73
            $decoded = JWT::decode($token, $this->secret, ['HS256']);
74
75
            if (!isset($decoded->exp) || $decoded->exp < time()) {
76
                return false;
77
            }
78
        } catch (ExpiredException $e) {
79
            return false;
80
        }
81
82
        $this->accessToken = $accessToken;
83
84
        return true;
85
    }
86
87
    /**
88
     * Checks if a Refresh Token is valid.
89
     *
90
     * @param string $token
91
     *
92
     * @return bool
93
     */
94 View Code Duplication
    public function checkRefreshToken($token)
95
    {
96
        $refreshToken = RefreshToken::where('token', $token)->first();
97
98
        if (null === $refreshToken) {
99
            return false;
100
        }
101
102
        try {
103
            $decoded = JWT::decode($token, $this->secret, ['HS256']);
104
105
            if (!isset($decoded->exp) || $decoded->exp < time()) {
106
                return false;
107
            }
108
        } catch (ExpiredException $e) {
109
            return false;
110
        }
111
112
        return true;
113
    }
114
115
    /**
116
     * Generates a new Access Token.
117
     *
118
     * @param User $user
119
     * @param bool $save
120
     *
121
     * @return string
122
     */
123
    public function generateAccessToken(User $user, $save = false)
124
    {
125
        $time = time();
126
        $expiresAt = $time + $this->accessTokenLifetime;
127
128
        $payload = [
129
            'iat' => $time,
130
            'exp' => $expiresAt,
131
            'data' => [
132
                'userId' => $user->id
133
            ]
134
        ];
135
136
        if ($this->serverName) {
137
            $payload['iss'] = $this->serverName;
138
        }
139
140
        $token = JWT::encode($payload, $this->secret);
141
142 View Code Duplication
        if ($save) {
143
            $accessToken = new AccessToken([
144
                'token' => $token,
145
                'expires_at' => $expiresAt
146
            ]);
147
148
            $accessToken->user()->associate($user);
149
            try {
150
                $accessToken->save();
151
            } catch (QueryException $e) {
152
            }
153
        }
154
155
        return $token;
156
    }
157
158
    /**
159
     * Generates a new Refresh Token.
160
     *
161
     * @param User $user
162
     * @param bool $save
163
     *
164
     * @return string
165
     */
166
    public function generateRefreshToken(User $user, $save = false)
167
    {
168
        $time = time();
169
        $expiresAt = $time + $this->refreshTokenLifetime;
170
171
        $payload = [
172
            'iat' => $time,
173
            'exp' => $expiresAt,
174
            'data' => [
175
                'type' => 'refresh',
176
                'userId' => $user->id,
177
                'userName' => $user->username
0 ignored issues
show
The property username does not seem to exist on App\Security\Model\User. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
178
            ]
179
        ];
180
181
        if ($this->serverName) {
182
            $payload['iss'] = $this->serverName;
183
        }
184
185
        $token = JWT::encode($payload, $this->secret);
186
187 View Code Duplication
        if ($save) {
188
            $refreshToken = new RefreshToken([
189
                'token' => $token,
190
                'expires_at' => $expiresAt
191
            ]);
192
193
            $refreshToken->user()->associate($user);
194
            try {
195
                $refreshToken->save();
196
            } catch (QueryException $e) {
197
            }
198
        }
199
200
        return $token;
201
    }
202
203
    /**
204
     * Gets the User associated with the given Token.
205
     *
206
     * @param string $token
207
     *
208
     * @return User|null
209
     */
210
    public function getTokenUser($token) {
211
        try {
212
            $decoded = JWT::decode($token, $this->secret, ['HS256']);
213
214
            if (isset($decoded->data->userId)) {
215
                return User::find($decoded->data->userId);
216
            }
217
        } catch (ExpiredException $e) {
218
        }
219
220
        return null;
221
    }
222
223
    /**
224
     * Sets the server name.
225
     *
226
     * @param string $name
227
     */
228
    public function setServerName($name)
229
    {
230
        $this->serverName = $name;
231
    }
232
233
    /**
234
     * Gets the server name.
235
     *
236
     * @return string
237
     */
238
    public function getServerName()
239
    {
240
        return $this->serverName;
241
    }
242
243
    /**
244
     * Sets the Access Token lifetime.
245
     *
246
     * @param int $lifetime
247
     */
248
    public function setAccessTokenLifetime($lifetime)
249
    {
250
        $this->accessTokenLifetime = $lifetime;
251
    }
252
253
    /**
254
     * Gets the Access Token lifetime.
255
     *
256
     * @return int
257
     */
258
    public function getAccessTokenLifetime()
259
    {
260
        return $this->accessTokenLifetime;
261
    }
262
263
    /**
264
     * Sets the Refresh Token lifetime.
265
     *
266
     * @param int $lifetime
267
     */
268
    public function setRefreshTokenLifetime($lifetime)
269
    {
270
        $this->refreshTokenLifetime = $lifetime;
271
    }
272
273
    /**
274
     * Gets the Refresh Token lifetime.
275
     *
276
     * @return int
277
     */
278
    public function getRefreshTokenLifetime()
279
    {
280
        return $this->refreshTokenLifetime;
281
    }
282
283
    /**
284
     * Sets the Access Token.
285
     *
286
     * @param AccessToken $accessToken
287
     */
288
    public function setAccessToken(AccessToken $accessToken)
289
    {
290
        $this->accessToken = $accessToken;
291
    }
292
293
    /**
294
     * Gets the Access Token.
295
     *
296
     * @return AccessToken
297
     */
298
    public function getAccessToken()
299
    {
300
        return $this->accessToken;
301
    }
302
}
303