Completed
Push — master ( 2472b9...abe8f5 )
by Roman
02:20
created

Guard   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 215
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 11

Importance

Changes 3
Bugs 0 Features 2
Metric Value
c 3
b 0
f 2
dl 0
loc 215
wmc 25
lcom 1
cbo 11
rs 10

11 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 12 1
A token() 0 8 2
A setToken() 0 7 1
B user() 0 23 4
A setUser() 0 7 1
A getTokenForRequest() 0 20 4
A validate() 0 10 3
A attempt() 0 8 2
A createTokenForUser() 0 19 3
A logout() 0 17 3
A setRequest() 0 6 1
1
<?php
2
3
namespace Framgia\Jwt;
4
5
use Carbon\Carbon;
6
use Framgia\Jwt\Contracts\ChecksClaims;
7
use Illuminate\Contracts\Auth\Authenticatable;
8
use Illuminate\Support\Str;
9
use Lcobucci\JWT\Parser;
10
use Lcobucci\JWT\Builder;
11
use Illuminate\Http\Request;
12
use InvalidArgumentException;
13
use Framgia\Jwt\Contracts\Signer;
14
use Illuminate\Auth\GuardHelpers;
15
use Illuminate\Contracts\Auth\UserProvider;
16
use Framgia\Jwt\Contracts\ProvidesCredentials;
17
use Illuminate\Contracts\Auth\Guard as GuardContract;
18
use Lcobucci\JWT\Token;
19
20
class Guard implements GuardContract
21
{
22
    use GuardHelpers;
23
24
    /**
25
     * The request instance.
26
     *
27
     * @var \Illuminate\Http\Request
28
     */
29
    protected $request;
30
31
    /**
32
     * @var \Framgia\Jwt\Blacklist
33
     */
34
    protected $blacklist;
35
36
    /**
37
     * @var \Framgia\Jwt\Contracts\Signer
38
     */
39
    protected $signer;
40
41
    /**
42
     * @var \Lcobucci\JWT\Token
43
     */
44
    protected $token;
45
46
    /**
47
     * Create a new authentication guard.
48
     *
49
     * @param  \Illuminate\Contracts\Auth\UserProvider  $provider
50
     * @param  \Illuminate\Http\Request  $request
51
     * @param  \Framgia\Jwt\Blacklist  $blacklist
52
     * @param  \Framgia\Jwt\Contracts\Signer  $signer
53
     */
54
    public function __construct(
55
        UserProvider $provider,
56
        Request $request,
57
        Blacklist $blacklist,
58
        Signer $signer
59
    )
60
    {
61
        $this->request = $request;
62
        $this->provider = $provider;
63
        $this->blacklist = $blacklist;
64
        $this->signer = $signer;
65
    }
66
67
    public function token()
68
    {
69
        if (empty($this->token)) {
70
            $this->token = $this->getTokenForRequest();
71
        }
72
73
        return $this->token;
74
    }
75
76
    public function setToken(Token $token)
77
    {
78
        $this->token = $token;
79
        $this->user = null;
80
81
        return $this;
82
    }
83
84
    /**
85
     * Get the currently authenticated user.
86
     *
87
     * @return \Illuminate\Contracts\Auth\Authenticatable|null
88
     */
89
    public function user()
90
    {
91
        // If we've already retrieved the user for the current request we can just
92
        // return it back immediately. We do not want to fetch the user data on
93
        // every call to this method because that would be tremendously slow.
94
        if (! is_null($this->user)) {
95
            return $this->user;
96
        }
97
98
        $user = null;
99
100
        $token = $this->token();
101
102
        if (! is_null($token)) {
103
            if ($this->provider instanceof ChecksClaims) {
104
                $user = $this->provider->retrieveByClaims($token->getClaims());
105
            } else {
106
                $user = $this->provider->retrieveById($token->getClaim('sub'));
107
            }
108
        }
109
110
        return $this->user = $user;
111
    }
112
113
    public function setUser(Authenticatable $user)
114
    {
115
        $this->user = $user;
116
        $this->token = $this->createTokenForUser($this->user);
117
118
        return $this;
119
    }
120
121
    /**
122
     * Get the token for the current request.
123
     *
124
     * @return \Lcobucci\JWT\Token
125
     */
126
    protected function getTokenForRequest()
127
    {
128
        $token = $this->request->bearerToken();
129
130
        if (empty($token)) {
131
            return null;
132
        }
133
134
        try {
135
            $token = (new Parser())->parse($token);
136
137
            if (!$this->signer->verify($token)) {
138
                return null;
139
            }
140
        } catch (InvalidArgumentException $e) {
141
            return null;
142
        }
143
144
        return $token;
145
    }
146
147
    /**
148
     * Validate a user's credentials.
149
     *
150
     * @param  array  $credentials
151
     * @return bool
152
     */
153
    public function validate(array $credentials = [])
154
    {
155
        $user = $this->provider->retrieveByCredentials($credentials);
156
        if (!is_null($user) && $this->provider->validateCredentials($user, $credentials)) {
157
            $this->user = $user;
158
            return true;
159
        }
160
161
        return false;
162
    }
163
164
    /**
165
     * @param array $credentials
166
     * @return \Lcobucci\JWT\Token|null
167
     */
168
    public function attempt(array $credentials)
169
    {
170
        if (!$this->validate($credentials)) {
171
            return null;
172
        }
173
174
        return $this->token = $this->createTokenForUser($this->user);
175
    }
176
177
    /**
178
     * @param  Authenticatable  $user
179
     * @return Token
180
     */
181
    public function createTokenForUser(Authenticatable $user)
182
    {
183
        $builder = new Builder();
184
185
        $id = $user->getAuthIdentifier();
186
        $builder->setSubject($id);
187
188
        if ($user instanceof ProvidesCredentials) {
189
            foreach($user->getCredentials() as $key => $value) {
190
                $builder->set($key, $value);
191
            }
192
        }
193
194
        $builder->setExpiration(Carbon::now()->addDay()->timestamp);
195
196
        $builder->setId(Str::random());
197
198
        return $this->signer->sign($builder)->getToken();
199
    }
200
201
    /**
202
     * @return bool
203
     */
204
    public function logout()
205
    {
206
        $token = $this->getTokenForRequest();
207
208
        if (empty($token)) {
209
            $result = true;
210
        } else {
211
            $result = $this->blacklist->add($token);
212
        }
213
214
        if ($result) {
215
            $this->token = null;
216
            $this->user = null;
217
        }
218
219
        return $result;
220
    }
221
222
    /**
223
     * Set the current request instance.
224
     *
225
     * @param  \Illuminate\Http\Request  $request
226
     * @return $this
227
     */
228
    public function setRequest(Request $request)
229
    {
230
        $this->request = $request;
231
232
        return $this;
233
    }
234
}
235