Completed
Push — master ( 80080e...676347 )
by Artem
03:07
created

TokenGuard::getLastError()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
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
     * The last error message.
50
     *
51
     * @var string
52
     */
53
    protected $lastError;
54
55
    /**
56
     * TokenGuard constructor.
57
     *
58
     * @param UserProvider $provider
59
     * @param Request $request
60
     * @param AuthService $authService
61
     * @param Client|null $client
62
     */
63
    public function __construct(
64
        UserProvider $provider,
65
        Request $request,
66
        AuthService $authService,
67
        Client $client = null
68
    )
69
    {
70
        $this->provider = $provider;
71
        $this->request = $request;
72
        $this->authService = $authService;
73
74
        $this->client = $client ?? new Client();
75
    }
76
77
    /**
78
     * Authenticate a user.
79
     *
80
     * @param string $email
81
     * @param string $password
82
     * @param bool $remember
83
     *
84
     * @return mixed
85
     *
86
     * @throws
87
     */
88
    public function login(string $email, string $password, bool $remember = false)
89
    {
90
        $response = $this->client->request('login', compact('email', 'password', 'remember'));
91
92
        if(!$this->client->success(true)) {
93
            $this->lastError = array_get($response, 'message');
94
            return false;
95
        }
96
97
        if(!$this->token = $this->client->getToken()) {
98
            return false;
99
        }
100
101
        $this->storeToken($this->token);
102
103
        return $this->token;
104
    }
105
106
    /**
107
     * Authenticate a user without the password.
108
     *
109
     * Warning! This method has implemented temporarily to make able to login users
110
     * who use Social Auth on 24Templates. MUST NOT be used in any other cases.
111
     *
112
     * @param string $email
113
     * @param string $password
114
     * @param bool $remember
115
     *
116
     * @return mixed
117
     *
118
     * @throws
119
     */
120
    public function unsafeLogin(string $email, bool $remember = false)
121
    {
122
        $this->client->request('unsafeLogin', compact('email', 'remember'));
123
124
        if(!$this->client->success()) {
125
            return false;
126
        }
127
128
        if(!$this->token = $this->client->getToken()) {
129
            return false;
130
        }
131
132
        $this->storeToken($this->token);
133
134
        return $this->token;
135
    }
136
137
    /**
138
     * Get the currently authenticated user.
139
     *
140
     * @return \Illuminate\Contracts\Auth\Authenticatable|null
141
     */
142
    public function user()
143
    {
144
        // If we've already retrieved the user for the current request we can just
145
        // return it back immediately. We do not want to fetch the user data on
146
        // every call to this method because that would be tremendously slow.
147
        if (! is_null($this->user)) {
148
            return $this->user;
149
        }
150
151
        $user = null;
152
153
        if($token = $this->token()) {
154
            $user = $this->retrieveUserFromToken($token);
155
        }
156
157
        return $this->user = $user;
158
    }
159
160
    /**
161
     * Get the token for the current request.
162
     *
163
     * @return string|null
164
     */
165
    public function token()
166
    {
167
        if($this->token) {
168
            return $this->token;
169
        }
170
171
        $token = $this->request->cookie($this->authCookie);
172
173
        if (empty($token)) {
174
            $token = $this->request->bearerToken();
175
        }
176
177
        return $this->token = $token;
178
    }
179
180
    /**
181
     * Validate a user's credentials.
182
     *
183
     * @param  array  $credentials
184
     * @return bool
185
     */
186
    public function validate(array $credentials = [])
187
    {
188
        return true;
189
    }
190
191
    /**
192
     * Store a token
193
     *
194
     * @param string $token
195
     */
196
    private function storeToken(string $token)
197
    {
198
        $cookie = cookie($this->authCookie, $token);
199
200
        Cookie::queue($cookie);
201
    }
202
203
    /**
204
     * Retrieve a user model from the parsed JWT token.
205
     *
206
     * @param string $token
207
     *
208
     * @return \Illuminate\Contracts\Auth\Authenticatable|\Illuminate\Database\Query\Builder|null
209
     */
210
    private function retrieveUserFromToken(string $token)
211
    {
212
        try
213
        {
214
            $data = (array) \Firebase\JWT\JWT::decode($token, env('JWT_SECRET'), ['HS256']);
215
        }
216
        catch(\RuntimeException $e) {
217
            $this->logout();
218
219
            return null;
220
        }
221
222
        if(!$userId = array_get($data, 'userId')) {
223
            return null;
224
        }
225
226
        return $this->provider->retrieveByCredentials(['remote_id' => $userId]);
227
    }
228
229
    /**
230
     * Invalidate a cookie
231
     *
232
     * @return void
233
     */
234
    public function logout()
235
    {
236
        Cookie::queue(Cookie::forget($this->authCookie));
237
    }
238
239
    /**
240
     * Get last error message from the server.
241
     *
242
     * @return string|null
243
     */
244
    public function getLastError(): ?string
245
    {
246
        return $this->lastError;
247
    }
248
}