1 | <?php declare(strict_types=1); |
||||||||||||||||||||
2 | |||||||||||||||||||||
3 | namespace Firesphere\GraphQLJWT\Authentication; |
||||||||||||||||||||
4 | |||||||||||||||||||||
5 | use BadMethodCallException; |
||||||||||||||||||||
6 | use DateTimeImmutable; |
||||||||||||||||||||
7 | use Exception; |
||||||||||||||||||||
8 | use Firesphere\GraphQLJWT\Extensions\MemberExtension; |
||||||||||||||||||||
9 | use Firesphere\GraphQLJWT\Helpers\MemberTokenGenerator; |
||||||||||||||||||||
10 | use Firesphere\GraphQLJWT\Model\JWTRecord; |
||||||||||||||||||||
11 | use Firesphere\GraphQLJWT\Types\TokenStatusEnum; |
||||||||||||||||||||
12 | use Lcobucci\JWT\Builder; |
||||||||||||||||||||
13 | use Lcobucci\JWT\Parser; |
||||||||||||||||||||
14 | use Lcobucci\JWT\Signer; |
||||||||||||||||||||
15 | use Lcobucci\JWT\Signer\Hmac; |
||||||||||||||||||||
16 | use Lcobucci\JWT\Signer\Key; |
||||||||||||||||||||
17 | use Lcobucci\JWT\Signer\Rsa; |
||||||||||||||||||||
18 | use Lcobucci\JWT\Token; |
||||||||||||||||||||
19 | use Lcobucci\JWT\ValidationData; |
||||||||||||||||||||
20 | use LogicException; |
||||||||||||||||||||
21 | use OutOfBoundsException; |
||||||||||||||||||||
22 | use SilverStripe\Control\Director; |
||||||||||||||||||||
23 | use SilverStripe\Control\HTTPRequest; |
||||||||||||||||||||
24 | use SilverStripe\Core\Config\Configurable; |
||||||||||||||||||||
25 | use SilverStripe\Core\Environment; |
||||||||||||||||||||
26 | use SilverStripe\Core\Injector\Injectable; |
||||||||||||||||||||
27 | use SilverStripe\ORM\FieldType\DBDatetime; |
||||||||||||||||||||
28 | use SilverStripe\ORM\ValidationException; |
||||||||||||||||||||
29 | use SilverStripe\ORM\ValidationResult; |
||||||||||||||||||||
30 | use SilverStripe\Security\Authenticator; |
||||||||||||||||||||
31 | use SilverStripe\Security\Member; |
||||||||||||||||||||
32 | use SilverStripe\Security\MemberAuthenticator\MemberAuthenticator; |
||||||||||||||||||||
33 | |||||||||||||||||||||
34 | class JWTAuthenticator extends MemberAuthenticator |
||||||||||||||||||||
35 | { |
||||||||||||||||||||
36 | use Injectable; |
||||||||||||||||||||
37 | use Configurable; |
||||||||||||||||||||
38 | use MemberTokenGenerator; |
||||||||||||||||||||
39 | |||||||||||||||||||||
40 | const JWT_SIGNER_KEY = 'JWT_SIGNER_KEY'; |
||||||||||||||||||||
41 | |||||||||||||||||||||
42 | const JWT_KEY_PASSWORD = 'JWT_KEY_PASSWORD'; |
||||||||||||||||||||
43 | |||||||||||||||||||||
44 | const JWT_PUBLIC_KEY = 'JWT_PUBLIC_KEY'; |
||||||||||||||||||||
45 | |||||||||||||||||||||
46 | /** |
||||||||||||||||||||
47 | * Key is RSA public/private pair |
||||||||||||||||||||
48 | */ |
||||||||||||||||||||
49 | const RSA = 'RSA'; |
||||||||||||||||||||
50 | |||||||||||||||||||||
51 | /** |
||||||||||||||||||||
52 | * Key is RSA public/private pair, with password enabled |
||||||||||||||||||||
53 | */ |
||||||||||||||||||||
54 | const RSA_PASSWORD = 'RSA_PASSWORD'; |
||||||||||||||||||||
55 | |||||||||||||||||||||
56 | /** |
||||||||||||||||||||
57 | * Key is HMAC string |
||||||||||||||||||||
58 | */ |
||||||||||||||||||||
59 | const HMAC = 'HMAC'; |
||||||||||||||||||||
60 | |||||||||||||||||||||
61 | /** |
||||||||||||||||||||
62 | * Set to true to allow anonymous JWT tokens (no member record / email / password) |
||||||||||||||||||||
63 | * |
||||||||||||||||||||
64 | * @config |
||||||||||||||||||||
65 | * @var bool |
||||||||||||||||||||
66 | */ |
||||||||||||||||||||
67 | private static $anonymous_allowed = false; |
||||||||||||||||||||
0 ignored issues
–
show
introduced
by
![]() |
|||||||||||||||||||||
68 | |||||||||||||||||||||
69 | /** |
||||||||||||||||||||
70 | * @config |
||||||||||||||||||||
71 | * @var int |
||||||||||||||||||||
72 | */ |
||||||||||||||||||||
73 | private static $nbf_time = 0; |
||||||||||||||||||||
0 ignored issues
–
show
|
|||||||||||||||||||||
74 | |||||||||||||||||||||
75 | /** |
||||||||||||||||||||
76 | * Expires after 1 hour |
||||||||||||||||||||
77 | * |
||||||||||||||||||||
78 | * @config |
||||||||||||||||||||
79 | * @var int |
||||||||||||||||||||
80 | */ |
||||||||||||||||||||
81 | private static $nbf_expiration = 3600; |
||||||||||||||||||||
0 ignored issues
–
show
|
|||||||||||||||||||||
82 | |||||||||||||||||||||
83 | /** |
||||||||||||||||||||
84 | * Token can be refreshed within 7 days |
||||||||||||||||||||
85 | * |
||||||||||||||||||||
86 | * @config |
||||||||||||||||||||
87 | * @var int |
||||||||||||||||||||
88 | */ |
||||||||||||||||||||
89 | private static $nbf_refresh_expiration = 604800; |
||||||||||||||||||||
0 ignored issues
–
show
|
|||||||||||||||||||||
90 | |||||||||||||||||||||
91 | /** |
||||||||||||||||||||
92 | * Keys are one of: |
||||||||||||||||||||
93 | * - public / private RSA pair files |
||||||||||||||||||||
94 | * - public / private RSA pair files, password protected private key |
||||||||||||||||||||
95 | * - private HMAC string |
||||||||||||||||||||
96 | * |
||||||||||||||||||||
97 | * @return string |
||||||||||||||||||||
98 | */ |
||||||||||||||||||||
99 | protected function getKeyType(): string |
||||||||||||||||||||
100 | { |
||||||||||||||||||||
101 | $signerKey = $this->getEnv(self::JWT_SIGNER_KEY); |
||||||||||||||||||||
102 | $path = $this->resolvePath($signerKey); |
||||||||||||||||||||
103 | if (!$path) { |
||||||||||||||||||||
104 | return self::HMAC; |
||||||||||||||||||||
105 | } |
||||||||||||||||||||
106 | if ($this->getEnv(self::JWT_KEY_PASSWORD, null)) { |
||||||||||||||||||||
107 | return self::RSA_PASSWORD; |
||||||||||||||||||||
108 | } |
||||||||||||||||||||
109 | return self::RSA; |
||||||||||||||||||||
110 | } |
||||||||||||||||||||
111 | |||||||||||||||||||||
112 | /** |
||||||||||||||||||||
113 | * @return Signer |
||||||||||||||||||||
114 | */ |
||||||||||||||||||||
115 | protected function getSigner(): Signer |
||||||||||||||||||||
116 | { |
||||||||||||||||||||
117 | switch ($this->getKeyType()) { |
||||||||||||||||||||
118 | case self::HMAC: |
||||||||||||||||||||
119 | return new Hmac\Sha256(); |
||||||||||||||||||||
120 | case self::RSA: |
||||||||||||||||||||
121 | case self::RSA_PASSWORD: |
||||||||||||||||||||
122 | default: |
||||||||||||||||||||
123 | return new Rsa\Sha256(); |
||||||||||||||||||||
124 | } |
||||||||||||||||||||
125 | } |
||||||||||||||||||||
126 | |||||||||||||||||||||
127 | /** |
||||||||||||||||||||
128 | * Get private key used to generate JWT tokens |
||||||||||||||||||||
129 | * |
||||||||||||||||||||
130 | * @return Key |
||||||||||||||||||||
131 | */ |
||||||||||||||||||||
132 | protected function getPrivateKey(): Key |
||||||||||||||||||||
133 | { |
||||||||||||||||||||
134 | // Note: Only private key has password enabled |
||||||||||||||||||||
135 | $password = $this->getEnv(self::JWT_KEY_PASSWORD, null); |
||||||||||||||||||||
136 | return $this->makeKey(self::JWT_SIGNER_KEY, $password); |
||||||||||||||||||||
137 | } |
||||||||||||||||||||
138 | |||||||||||||||||||||
139 | /** |
||||||||||||||||||||
140 | * Get public key used to validate JWT tokens |
||||||||||||||||||||
141 | * |
||||||||||||||||||||
142 | * @return Key |
||||||||||||||||||||
143 | * @throws LogicException |
||||||||||||||||||||
144 | */ |
||||||||||||||||||||
145 | protected function getPublicKey(): Key |
||||||||||||||||||||
146 | { |
||||||||||||||||||||
147 | switch ($this->getKeyType()) { |
||||||||||||||||||||
148 | case self::HMAC: |
||||||||||||||||||||
149 | // If signer key is a HMAC string instead of a path, public key == private key |
||||||||||||||||||||
150 | return $this->getPrivateKey(); |
||||||||||||||||||||
151 | default: |
||||||||||||||||||||
152 | // If signer key is a path to RSA token, then we require a separate public key path |
||||||||||||||||||||
153 | return $this->makeKey(self::JWT_PUBLIC_KEY); |
||||||||||||||||||||
154 | } |
||||||||||||||||||||
155 | } |
||||||||||||||||||||
156 | |||||||||||||||||||||
157 | /** |
||||||||||||||||||||
158 | * Construct a new key from the named config variable |
||||||||||||||||||||
159 | * |
||||||||||||||||||||
160 | * @param string $name Key name |
||||||||||||||||||||
161 | * @param string|null $password Optional password |
||||||||||||||||||||
162 | * @return Key |
||||||||||||||||||||
163 | */ |
||||||||||||||||||||
164 | private function makeKey(string $name, string $password = null): Key |
||||||||||||||||||||
165 | { |
||||||||||||||||||||
166 | $key = $this->getEnv($name); |
||||||||||||||||||||
167 | $path = $this->resolvePath($key); |
||||||||||||||||||||
168 | |||||||||||||||||||||
169 | // String key |
||||||||||||||||||||
170 | if (empty($path)) { |
||||||||||||||||||||
171 | return new Key($path); |
||||||||||||||||||||
172 | } |
||||||||||||||||||||
173 | |||||||||||||||||||||
174 | // Build key from path |
||||||||||||||||||||
175 | return new Key('file://' . $path, $password); |
||||||||||||||||||||
176 | } |
||||||||||||||||||||
177 | |||||||||||||||||||||
178 | /** |
||||||||||||||||||||
179 | * JWT is stateless, therefore, we don't support anything but login |
||||||||||||||||||||
180 | * |
||||||||||||||||||||
181 | * @return int |
||||||||||||||||||||
182 | */ |
||||||||||||||||||||
183 | public function supportedServices(): int |
||||||||||||||||||||
184 | { |
||||||||||||||||||||
185 | return Authenticator::LOGIN; |
||||||||||||||||||||
186 | } |
||||||||||||||||||||
187 | |||||||||||||||||||||
188 | /** |
||||||||||||||||||||
189 | * @param array $data |
||||||||||||||||||||
190 | * @param HTTPRequest $request |
||||||||||||||||||||
191 | * @param ValidationResult|null $result |
||||||||||||||||||||
192 | * @return Member|null |
||||||||||||||||||||
193 | * @throws OutOfBoundsException |
||||||||||||||||||||
194 | * @throws BadMethodCallException |
||||||||||||||||||||
195 | * @throws Exception |
||||||||||||||||||||
196 | */ |
||||||||||||||||||||
197 | public function authenticate(array $data, HTTPRequest $request, ValidationResult &$result = null): ?Member |
||||||||||||||||||||
198 | { |
||||||||||||||||||||
199 | if (!$result) { |
||||||||||||||||||||
200 | $result = new ValidationResult(); |
||||||||||||||||||||
201 | } |
||||||||||||||||||||
202 | $token = $data['token']; |
||||||||||||||||||||
203 | |||||||||||||||||||||
204 | /** @var JWTRecord $record */ |
||||||||||||||||||||
205 | list($record, $status) = $this->validateToken($token, $request); |
||||||||||||||||||||
206 | |||||||||||||||||||||
207 | // Report success! |
||||||||||||||||||||
208 | if ($status === TokenStatusEnum::STATUS_OK) { |
||||||||||||||||||||
209 | return $record->Member(); |
||||||||||||||||||||
210 | } |
||||||||||||||||||||
211 | |||||||||||||||||||||
212 | // Add errors to result |
||||||||||||||||||||
213 | $result->addError( |
||||||||||||||||||||
214 | $this->getErrorMessage($status), |
||||||||||||||||||||
215 | ValidationResult::TYPE_ERROR, |
||||||||||||||||||||
216 | $status |
||||||||||||||||||||
217 | ); |
||||||||||||||||||||
218 | return null; |
||||||||||||||||||||
219 | } |
||||||||||||||||||||
220 | |||||||||||||||||||||
221 | /** |
||||||||||||||||||||
222 | * Generate a new JWT token for a given request, and optional (if anonymous_allowed) user |
||||||||||||||||||||
223 | * |
||||||||||||||||||||
224 | * @param HTTPRequest $request |
||||||||||||||||||||
225 | * @param Member|MemberExtension $member |
||||||||||||||||||||
226 | * @return Token |
||||||||||||||||||||
227 | * @throws ValidationException |
||||||||||||||||||||
228 | */ |
||||||||||||||||||||
229 | public function generateToken(HTTPRequest $request, Member $member): Token |
||||||||||||||||||||
230 | { |
||||||||||||||||||||
231 | $config = static::config(); |
||||||||||||||||||||
232 | $uniqueID = uniqid($this->getEnv('JWT_PREFIX', ''), true); |
||||||||||||||||||||
233 | |||||||||||||||||||||
234 | // Create new record |
||||||||||||||||||||
235 | $record = new JWTRecord(); |
||||||||||||||||||||
236 | $record->UID = $uniqueID; |
||||||||||||||||||||
237 | $record->UserAgent = $request->getHeader('User-Agent'); |
||||||||||||||||||||
238 | $member->AuthTokens()->add($record); |
||||||||||||||||||||
239 | if (!$record->isInDB()) { |
||||||||||||||||||||
240 | $record->write(); |
||||||||||||||||||||
241 | } |
||||||||||||||||||||
242 | |||||||||||||||||||||
243 | // Create builder for this record |
||||||||||||||||||||
244 | $builder = new Builder(); |
||||||||||||||||||||
245 | $now = DBDatetime::now()->getTimestamp(); |
||||||||||||||||||||
246 | $token = $builder |
||||||||||||||||||||
0 ignored issues
–
show
The function
Lcobucci\JWT\Builder::setIssuedAt() has been deprecated: This method will be removed on v4
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() The function
Lcobucci\JWT\Builder::setSubject() has been deprecated: This method will be removed on v4
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() The function
Lcobucci\JWT\Builder::setAudience() has been deprecated: This method will be removed on v4
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() The function
Lcobucci\JWT\Builder::setId() has been deprecated: This method will be removed on v4
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() The function
Lcobucci\JWT\Builder::sign() has been deprecated: This method will be removed on v4
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() The function
Lcobucci\JWT\Builder::set() has been deprecated: This method will be removed on v4
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() The function
Lcobucci\JWT\Builder::setExpiration() has been deprecated: This method will be removed on v4
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() The function
Lcobucci\JWT\Builder::setIssuer() has been deprecated: This method will be removed on v4
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() The function
Lcobucci\JWT\Builder::setNotBefore() has been deprecated: This method will be removed on v4
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||||||||||||||||||
247 | // Configures the issuer (iss claim) |
||||||||||||||||||||
248 | ->setIssuer($request->getHeader('Origin')) |
||||||||||||||||||||
249 | // Configures the audience (aud claim) |
||||||||||||||||||||
250 | ->setAudience(Director::absoluteBaseURL()) |
||||||||||||||||||||
251 | // Configures the id (jti claim), replicating as a header item |
||||||||||||||||||||
252 | ->setId($uniqueID, true) |
||||||||||||||||||||
253 | // Configures the time that the token was issue (iat claim) |
||||||||||||||||||||
254 | ->setIssuedAt($now) |
||||||||||||||||||||
255 | // Configures the time that the token can be used (nbf claim) |
||||||||||||||||||||
256 | ->setNotBefore($now + $config->get('nbf_time')) |
||||||||||||||||||||
257 | // Configures the expiration time of the token (nbf claim) |
||||||||||||||||||||
258 | ->setExpiration($now + $config->get('nbf_expiration')) |
||||||||||||||||||||
259 | // Set renew expiration |
||||||||||||||||||||
260 | ->set('rexp', $now + $config->get('nbf_refresh_expiration')) |
||||||||||||||||||||
261 | // Configures a new claim, called "rid" |
||||||||||||||||||||
262 | ->set('rid', $record->ID) |
||||||||||||||||||||
263 | // Set the subject, which is the member |
||||||||||||||||||||
264 | ->setSubject($member->getJWTData()) |
||||||||||||||||||||
265 | // Sign the key with the Signer's key |
||||||||||||||||||||
266 | ->sign($this->getSigner(), $this->getPrivateKey()); |
||||||||||||||||||||
267 | |||||||||||||||||||||
268 | // Return the token |
||||||||||||||||||||
269 | return $token->getToken(); |
||||||||||||||||||||
270 | } |
||||||||||||||||||||
271 | |||||||||||||||||||||
272 | /** |
||||||||||||||||||||
273 | * @param string $token |
||||||||||||||||||||
274 | * @param HTTPRequest $request |
||||||||||||||||||||
275 | * @return array|null Array with JWTRecord and int status (STATUS_*) |
||||||||||||||||||||
276 | * @throws BadMethodCallException|Exception |
||||||||||||||||||||
277 | */ |
||||||||||||||||||||
278 | public function validateToken(?string $token, HTTPrequest $request): array |
||||||||||||||||||||
279 | { |
||||||||||||||||||||
280 | // Parse token |
||||||||||||||||||||
281 | $parsedToken = $this->parseToken($token); |
||||||||||||||||||||
282 | if (!$parsedToken) { |
||||||||||||||||||||
283 | return [null, TokenStatusEnum::STATUS_INVALID]; |
||||||||||||||||||||
284 | } |
||||||||||||||||||||
285 | |||||||||||||||||||||
286 | // Find local record for this token |
||||||||||||||||||||
287 | /** @var JWTRecord $record */ |
||||||||||||||||||||
288 | $record = JWTRecord::get()->byID($parsedToken->getClaim('rid')); |
||||||||||||||||||||
0 ignored issues
–
show
The function
Lcobucci\JWT\Token::getClaim() has been deprecated: This method has been removed from the interface in v4.0
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||||||||||||||||||
289 | if (!$record) { |
||||||||||||||||||||
0 ignored issues
–
show
|
|||||||||||||||||||||
290 | return [null, TokenStatusEnum::STATUS_INVALID]; |
||||||||||||||||||||
291 | } |
||||||||||||||||||||
292 | |||||||||||||||||||||
293 | // Verified and valid = ok! |
||||||||||||||||||||
294 | $valid = $this->validateParsedToken($parsedToken, $request, $record); |
||||||||||||||||||||
295 | if ($valid) { |
||||||||||||||||||||
296 | return [$record, TokenStatusEnum::STATUS_OK]; |
||||||||||||||||||||
297 | } |
||||||||||||||||||||
298 | |||||||||||||||||||||
299 | // If the token is invalid, but not because it has expired, fail |
||||||||||||||||||||
300 | $now = new DateTimeImmutable(DBDatetime::now()->getValue()); |
||||||||||||||||||||
301 | if (!$parsedToken->isExpired($now)) { |
||||||||||||||||||||
302 | return [$record, TokenStatusEnum::STATUS_INVALID]; |
||||||||||||||||||||
303 | } |
||||||||||||||||||||
304 | |||||||||||||||||||||
305 | // If expired, check if it can be renewed |
||||||||||||||||||||
306 | $canReniew = $this->canTokenBeRenewed($parsedToken); |
||||||||||||||||||||
307 | if ($canReniew) { |
||||||||||||||||||||
308 | return [$record, TokenStatusEnum::STATUS_EXPIRED]; |
||||||||||||||||||||
309 | } |
||||||||||||||||||||
310 | |||||||||||||||||||||
311 | // If expired and cannot be renewed, it's dead |
||||||||||||||||||||
312 | return [$record, TokenStatusEnum::STATUS_DEAD]; |
||||||||||||||||||||
313 | } |
||||||||||||||||||||
314 | |||||||||||||||||||||
315 | /** |
||||||||||||||||||||
316 | * Parse a string into a token |
||||||||||||||||||||
317 | * |
||||||||||||||||||||
318 | * @param string|null $token |
||||||||||||||||||||
319 | * @return Token|null |
||||||||||||||||||||
320 | */ |
||||||||||||||||||||
321 | protected function parseToken(?string $token): ?Token |
||||||||||||||||||||
322 | { |
||||||||||||||||||||
323 | // Ensure token given at all |
||||||||||||||||||||
324 | if (!$token) { |
||||||||||||||||||||
325 | return null; |
||||||||||||||||||||
326 | } |
||||||||||||||||||||
327 | |||||||||||||||||||||
328 | try { |
||||||||||||||||||||
329 | // Verify parsed token matches signer |
||||||||||||||||||||
330 | $parser = new Parser(); |
||||||||||||||||||||
331 | $parsedToken = $parser->parse($token); |
||||||||||||||||||||
332 | } catch (Exception $ex) { |
||||||||||||||||||||
333 | // Un-parsable tokens are invalid |
||||||||||||||||||||
334 | return null; |
||||||||||||||||||||
335 | } |
||||||||||||||||||||
336 | |||||||||||||||||||||
337 | // Verify this token with configured keys |
||||||||||||||||||||
338 | $verified = $parsedToken->verify($this->getSigner(), $this->getPublicKey()); |
||||||||||||||||||||
0 ignored issues
–
show
The function
Lcobucci\JWT\Token::verify() has been deprecated: This method has been removed from the interface in v4.0
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||||||||||||||||||
339 | return $verified ? $parsedToken : null; |
||||||||||||||||||||
340 | } |
||||||||||||||||||||
341 | |||||||||||||||||||||
342 | /** |
||||||||||||||||||||
343 | * Determine if the given token is current, given the context of the current request |
||||||||||||||||||||
344 | * |
||||||||||||||||||||
345 | * @param Token $parsedToken |
||||||||||||||||||||
346 | * @param HTTPRequest $request |
||||||||||||||||||||
347 | * @param JWTRecord $record |
||||||||||||||||||||
348 | * @return bool |
||||||||||||||||||||
349 | */ |
||||||||||||||||||||
350 | protected function validateParsedToken(Token $parsedToken, HTTPrequest $request, JWTRecord $record): bool |
||||||||||||||||||||
351 | { |
||||||||||||||||||||
352 | $now = DBDatetime::now()->getTimestamp(); |
||||||||||||||||||||
353 | $validator = new ValidationData(); |
||||||||||||||||||||
0 ignored issues
–
show
The class
Lcobucci\JWT\ValidationData has been deprecated: This component has been removed from the interface in v4.0
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||||||||||||||||
354 | $validator->setIssuer($request->getHeader('Origin')); |
||||||||||||||||||||
355 | $validator->setAudience(Director::absoluteBaseURL()); |
||||||||||||||||||||
356 | $validator->setId($record->UID); |
||||||||||||||||||||
357 | $validator->setCurrentTime($now); |
||||||||||||||||||||
358 | return $parsedToken->validate($validator); |
||||||||||||||||||||
0 ignored issues
–
show
The function
Lcobucci\JWT\Token::validate() has been deprecated: This method has been removed from the interface in v4.0
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||||||||||||||||||
359 | } |
||||||||||||||||||||
360 | |||||||||||||||||||||
361 | /** |
||||||||||||||||||||
362 | * Check if the given token can be renewed |
||||||||||||||||||||
363 | * |
||||||||||||||||||||
364 | * @param Token $parsedToken |
||||||||||||||||||||
365 | * @return bool |
||||||||||||||||||||
366 | */ |
||||||||||||||||||||
367 | protected function canTokenBeRenewed(Token $parsedToken): bool |
||||||||||||||||||||
368 | { |
||||||||||||||||||||
369 | $renewBefore = $parsedToken->getClaim('rexp'); |
||||||||||||||||||||
0 ignored issues
–
show
The function
Lcobucci\JWT\Token::getClaim() has been deprecated: This method has been removed from the interface in v4.0
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||||||||||||||||||
370 | $now = DBDatetime::now()->getTimestamp(); |
||||||||||||||||||||
371 | return $renewBefore > $now; |
||||||||||||||||||||
372 | } |
||||||||||||||||||||
373 | |||||||||||||||||||||
374 | /** |
||||||||||||||||||||
375 | * Return an absolute path from a relative one |
||||||||||||||||||||
376 | * If the path doesn't exist, returns null |
||||||||||||||||||||
377 | * |
||||||||||||||||||||
378 | * @param string $path |
||||||||||||||||||||
379 | * @param string $base |
||||||||||||||||||||
380 | * @return string|null |
||||||||||||||||||||
381 | */ |
||||||||||||||||||||
382 | protected function resolvePath(string $path, string $base = BASE_PATH): ?string |
||||||||||||||||||||
383 | { |
||||||||||||||||||||
384 | if (strstr($path, '/') !== 0) { |
||||||||||||||||||||
385 | $path = $base . '/' . $path; |
||||||||||||||||||||
386 | } |
||||||||||||||||||||
387 | return realpath($path) ?: null; |
||||||||||||||||||||
388 | } |
||||||||||||||||||||
389 | |||||||||||||||||||||
390 | |||||||||||||||||||||
391 | /** |
||||||||||||||||||||
392 | * Get an environment value. If $default is not set and the environment isn't set either this will error. |
||||||||||||||||||||
393 | * |
||||||||||||||||||||
394 | * @param string $key |
||||||||||||||||||||
395 | * @param string|null $default |
||||||||||||||||||||
396 | * @return string|null |
||||||||||||||||||||
397 | * @throws LogicException Error if environment variable is required, but not configured |
||||||||||||||||||||
398 | */ |
||||||||||||||||||||
399 | protected function getEnv(string $key, $default = null): ?string |
||||||||||||||||||||
400 | { |
||||||||||||||||||||
401 | $value = Environment::getEnv($key); |
||||||||||||||||||||
402 | if ($value) { |
||||||||||||||||||||
403 | return $value; |
||||||||||||||||||||
404 | } |
||||||||||||||||||||
405 | if (func_num_args() === 1) { |
||||||||||||||||||||
406 | throw new LogicException("Required environment variable {$key} not set"); |
||||||||||||||||||||
407 | } |
||||||||||||||||||||
408 | return $default; |
||||||||||||||||||||
409 | } |
||||||||||||||||||||
410 | } |
||||||||||||||||||||
411 |