Completed
Push — master ( d7e260...fc7aea )
by Artem
10:19
created

TokenGuard::syncInstantly()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 0
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Slides\Connector\Auth;
4
5
use Illuminate\Http\Request;
6
use Illuminate\Auth\GuardHelpers;
7
use Illuminate\Support\Facades\Cookie;
8
use Illuminate\Contracts\Auth\UserProvider;
9
10
/**
11
 * Class TokenGuard
12
 *
13
 * @package App\Auth
14
 */
15
class TokenGuard implements \Illuminate\Contracts\Auth\Guard
16
{
17
    use GuardHelpers;
18
19
    /**
20
     * @var Request
21
     */
22
    protected $request;
23
24
    /**
25
     * @var Client
26
     */
27
    protected $client;
28
29
    /**
30
     * @var AuthService
31
     */
32
    protected $authService;
33
34
    /**
35
     * The name of cookie parameter where bearer token stores.
36
     *
37
     * @var string
38
     */
39
    protected $authCookie = 'authKey';
40
41
    /**
42
     * The JWT token
43
     *
44
     * @var string
45
     */
46
    protected $token;
47
48
    /**
49
     * TokenGuard constructor.
50
     *
51
     * @param UserProvider $provider
52
     * @param Request $request
53
     * @param AuthService $authService
54
     * @param Client|null $client
55
     */
56
    public function __construct(
57
        UserProvider $provider,
58
        Request $request,
59
        AuthService $authService,
60
        Client $client = null
61
    )
62
    {
63
        $this->provider = $provider;
64
        $this->request = $request;
65
        $this->authService = $authService;
66
67
        $this->client = $client ?? new Client();
68
    }
69
70
    /**
71
     * Authenticate a user.
72
     *
73
     * @param string $email
74
     * @param string $password
75
     * @param bool $remember
76
     *
77
     * @return mixed
78
     *
79
     * @throws
80
     */
81
    public function login(string $email, string $password, bool $remember = false)
82
    {
83
        $this->client->request('login', compact('email', 'password', 'remember'));
84
85
        if(!$this->client->success()) {
86
            return false;
87
        }
88
89
        if(!$this->token = $this->client->getToken()) {
90
            return false;
91
        }
92
93
        $this->storeToken($this->token);
94
95
        return $this->token;
96
    }
97
98
    /**
99
     * Authenticate a user without the password.
100
     *
101
     * Warning! This method has implemented temporarily to make able to login users
102
     * who use Social Auth on 24Templates. MUST NOT be used in any other cases.
103
     *
104
     * @param string $email
105
     * @param string $password
106
     * @param bool $remember
107
     *
108
     * @return mixed
109
     *
110
     * @throws
111
     */
112
    public function unsafeLogin(string $email, bool $remember = false)
113
    {
114
        $this->client->request('unsafeLogin', compact('email', 'remember'));
115
116
        if(!$this->client->success()) {
117
            return false;
118
        }
119
120
        if(!$this->token = $this->client->getToken()) {
121
            return false;
122
        }
123
124
        $this->storeToken($this->token);
125
126
        return $this->token;
127
    }
128
129
    /**
130
     * Get the currently authenticated user.
131
     *
132
     * @return \Illuminate\Contracts\Auth\Authenticatable|null
133
     */
134
    public function user()
135
    {
136
        // If we've already retrieved the user for the current request we can just
137
        // return it back immediately. We do not want to fetch the user data on
138
        // every call to this method because that would be tremendously slow.
139
        if (! is_null($this->user)) {
140
            return $this->user;
141
        }
142
143
        $user = null;
144
145
        if($token = $this->token()) {
146
            $user = $this->retrieveUserFromToken($token);
147
        }
148
149
        return $this->user = $user;
150
    }
151
152
    /**
153
     * Get the token for the current request.
154
     *
155
     * @return string|null
156
     */
157
    public function token()
158
    {
159
        if($this->token) {
160
            return $this->token;
161
        }
162
163
        $token = $this->request->cookie($this->authCookie);
164
165
        if (empty($token)) {
166
            $token = $this->request->bearerToken();
167
        }
168
169
        return $this->token = $token;
170
    }
171
172
    /**
173
     * Validate a user's credentials.
174
     *
175
     * @param  array  $credentials
176
     * @return bool
177
     */
178
    public function validate(array $credentials = [])
179
    {
180
        return true;
181
    }
182
183
    /**
184
     * Store a token
185
     *
186
     * @param string $token
187
     */
188
    private function storeToken(string $token)
189
    {
190
        $cookie = cookie($this->authCookie, $token);
191
192
        Cookie::queue($cookie);
193
    }
194
195
    /**
196
     * Retrieve a user model from the parsed JWT token.
197
     *
198
     * @param string $token
199
     *
200
     * @return \Illuminate\Contracts\Auth\Authenticatable|\Illuminate\Database\Query\Builder|null
201
     */
202
    private function retrieveUserFromToken(string $token)
203
    {
204
        try
205
        {
206
            $data = (array) \Firebase\JWT\JWT::decode($token, env('JWT_SECRET'), ['HS256']);
207
        }
208
        catch(\RuntimeException $e) {
209
            $this->logout();
210
211
            return null;
212
        }
213
214
        if(!$userId = array_get($data, 'userId')) {
215
            return null;
216
        }
217
218
        return $this->provider->retrieveByCredentials(['remote_id' => $userId]);
219
    }
220
221
    /**
222
     * Invalidate a cookie
223
     *
224
     * @return void
225
     */
226
    public function logout()
227
    {
228
        Cookie::queue(Cookie::forget($this->authCookie));
229
    }
230
}