Completed
Push — master ( 308b59...2472b9 )
by Roman
02:13
created

Guard::attempt()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

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