1 | <?php |
||
2 | |||
3 | namespace Firesphere\GraphQLJWT\Authentication; |
||
4 | |||
5 | use Firesphere\GraphQLJWT\Helpers\HeaderExtractor; |
||
6 | use SilverStripe\Control\HTTPRequest; |
||
7 | use SilverStripe\ORM\ValidationException; |
||
8 | use SilverStripe\Security\AuthenticationHandler; |
||
9 | use SilverStripe\Security\Member; |
||
10 | use SilverStripe\Security\Security; |
||
11 | |||
12 | /** |
||
13 | * Class JWTAuthenticationHandler |
||
14 | * |
||
15 | * |
||
16 | * @package Firesphere\GraphQLJWT |
||
17 | */ |
||
18 | class JWTAuthenticationHandler implements AuthenticationHandler |
||
19 | { |
||
20 | |||
21 | /** |
||
22 | * @var JWTAuthenticator |
||
23 | */ |
||
24 | protected $authenticator; |
||
25 | |||
26 | /** |
||
27 | * @return mixed |
||
28 | */ |
||
29 | public function getAuthenticator() |
||
30 | { |
||
31 | return $this->authenticator; |
||
32 | } |
||
33 | |||
34 | /** |
||
35 | * @param mixed $authenticator |
||
36 | */ |
||
37 | public function setAuthenticator($authenticator) |
||
38 | { |
||
39 | $this->authenticator = $authenticator; |
||
40 | } |
||
41 | |||
42 | /** |
||
43 | * @param HTTPRequest $request |
||
44 | * @return null|Member |
||
45 | * @throws \OutOfBoundsException |
||
46 | * @throws \BadMethodCallException |
||
47 | */ |
||
48 | public function authenticateRequest(HTTPRequest $request) |
||
49 | { |
||
50 | $matches = HeaderExtractor::getAuthorizationHeader($request); |
||
51 | // Get the default user currently logged in via a different way, could be BasicAuth/normal login |
||
52 | $member = Security::getCurrentUser(); |
||
53 | |||
54 | View Code Duplication | if (!empty($matches[1])) { |
|
0 ignored issues
–
show
|
|||
55 | // Validate the token. This is critical for security |
||
56 | $member = $this->authenticator->authenticate(['token' => $matches[1]], $request); |
||
57 | } |
||
58 | |||
59 | if ($member) { |
||
60 | $this->logIn($member); |
||
61 | } |
||
62 | |||
63 | return $member; |
||
64 | } |
||
65 | |||
66 | /** |
||
67 | * Authenticate on every run, based on the header, not relying on sessions or cookies |
||
68 | * JSON Web Tokens are stateless |
||
69 | * |
||
70 | * @param Member $member |
||
71 | * @param bool $persistent |
||
72 | * @param HTTPRequest|null $request |
||
73 | */ |
||
74 | public function logIn(Member $member, $persistent = false, HTTPRequest $request = null) |
||
75 | { |
||
76 | Security::setCurrentUser($member); |
||
77 | } |
||
78 | |||
79 | /** |
||
80 | * @param HTTPRequest|null $request |
||
81 | * @throws ValidationException |
||
82 | */ |
||
83 | public function logOut(HTTPRequest $request = null) |
||
84 | { |
||
85 | // A token can actually not be invalidated, but let's invalidate it's unique ID |
||
86 | // A member actually can be null though! |
||
87 | if ($request !== null) { // If we don't have a request, we're most probably in test mode |
||
88 | $member = Security::getCurrentUser(); |
||
89 | if ($member) { |
||
90 | // Set the unique ID to 0, as it can't be nullified due to indexes. |
||
91 | $member->JWTUniqueID = 0; |
||
92 | $member->write(); |
||
93 | } |
||
94 | } |
||
95 | // Empty the current user and pray to god it's not valid anywhere else anymore :) |
||
96 | Security::setCurrentUser(); |
||
97 | } |
||
98 | } |
||
99 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.