Completed
Push — master ( 57aa9a...9d09aa )
by Jacob
02:21
created

BaseGuard::generateToken()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 11
ccs 8
cts 8
cp 1
rs 9.4285
cc 2
eloc 8
nc 2
nop 1
crap 2
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016 Canis.io
4
 * @license   MIT
5
 */
6
namespace Canis\Lumen\Jwt;
7
8
use Illuminate\Http\Request;
9
use Illuminate\Auth\GuardHelpers;
10
use Illuminate\Contracts\Auth\Factory as AuthFactory;
11
use Illuminate\Contracts\Auth\UserProvider;
12
use Illuminate\Contracts\Auth\Guard as GaurdContract;
13
use Canis\Lumen\Jwt\Exceptions\InvalidTokenException;
14
use Canis\Lumen\Jwt\Exceptions\InvalidAdapterException;
15
use Canis\Lumen\Jwt\Contracts\AdapterFactory as AdapterFactoryContract;
16
use Canis\Lumen\Jwt\Contracts\Processor as ProcessorContract;
17
use Canis\Lumen\Jwt\Contracts\Subject as SubjectContract;
18
19
abstract class BaseGuard
20
    implements GaurdContract, GuardInterface
0 ignored issues
show
Coding Style introduced by
The implements keyword must be on the same line as the class name
Loading history...
21
{
22
    use GuardHelpers;
23
24
    const JWT_GUARD_CLAIM = 'grd';
25
26
    /**
27
     * @var string
28
     */
29
    protected $id;
30
31
    /**
32
     * @var Request
33
     */
34
    protected $request;
35
36
    /**
37
     * Constructor
38
     *
39
     * @param UserProvider $provider
40
     * @param Request      $request
41
     */
42 22
    public function __construct($id, UserProvider $provider, Request $request)
43
    {
44 22
        $this->request = $request;
45 22
        $this->provider = $provider;
46 22
        $this->id = $id;
47 22
    }
48
49
    /**
50
     * Returns the adapter class name to use
51
     *
52
     * @return string
53
     */
54 15
    public function getAdapterFactoryClass()
55
    {
56 15
        $config = config('jwt');
57 15
        if (!isset($config['adapter'])) {
58 13
            $config['adapter'] = 'lcobucci';
59 13
        }
60 15
        if (class_exists($config['adapter'])) {
61 1
            $factoryClass = $config['adapter'];
62 1
        } else {
63 14
            $factoryClass = 'Canis\Lumen\Jwt\Adapters\\' . ucfirst($config['adapter']) . '\Factory';
64 14
            if (!class_exists($factoryClass)) {
65 1
                throw new InvalidAdapterException("{$config['adapter']} is not available");
66
            }
67
        }
68 14
        return $factoryClass;
69
    }
70
71
    /**
72
     * Returns the adapter factory object
73
     *
74
     * @return AdapterFactoryContract
75
     */
76 15
    protected function getAdapterFactory()
77
    {
78 15
        static $factory;
79 15
        if (!isset($factory)) {
80 15
            $config = config('jwt');
81 15
            $factoryClass = $this->getAdapterFactoryClass();
82 14
            $factory = new $factoryClass($config);
83 14
        }
84 14
        return $factory;
85
    }
86
87
    /**
88
     * Returns a token processor from the adapter factory
89
     *
90
     * @return ProcessorContract
91
     */
92 11
    protected function getProcessor()
93
    {
94 11
        return $this->getAdapterFactory()->getProcessor();
95
    }
96
97
    /**
98
     * Returns a token generator from the adapter factory
99
     *
100
     * @return GeneratorContract
101
     */
102 7
    protected function getGenerator()
103
    {
104 7
        return $this->getAdapterFactory()->getGenerator();
105
    }
106
107
    /**
108
     * Gets the provider
109
     *
110
     * @return UserProvider
111
     */
112 14
    public function getProvider()
113
    {
114 14
        return $this->provider;
115
    }
116
117
118
    /**
119
     * @inheritdoc
120
     */
121 4
    public function refresh(AuthFactory $auth)
122
    {
123 4
        $token = $this->getBearerToken(true);
124 4
        if ($token !== false && $token->hasClaim(static::JWT_GUARD_CLAIM)) {
125 3
            $guard = $token->getClaim(static::JWT_GUARD_CLAIM);
126 3
            return $auth->guard($guard)->refreshToken($token);
127
        }
128 1
        return false;
129
    }
130
131
    /**
132
     * Refresh the token 
133
     * @param  Token  $token
134
     * @return Token|boolean  New token or false if old token can't be verified
135
     */
136 3
    public function refreshToken(Token $token)
137
    {
138 3
        $user = $this->getProvider()->retrieveById($token->getClaim('sub'));
139 3
        $claimValidation = [static::JWT_GUARD_CLAIM => $this->id];
140 3
        if (!($user instanceof SubjectContract)
141 3
            || !$token->ensureClaimValues(array_merge($user->getJWTClaimValidation(), $claimValidation))) {
142 1
            return false;
143
        }
144 2
        return $this->generateToken($user);
145
    }
146
147
    /**
148
     * @inheritdoc
149
     */
150 3
    public function universalUserLogin(AuthFactory $auth)
151
    {
152 3
        $token = $this->getBearerToken();
153 3
        $guard = false;
154 3
        if ($token !== false && $token->hasClaim(static::JWT_GUARD_CLAIM)) {
155 3
            $guard = $token->getClaim(static::JWT_GUARD_CLAIM);
156 3
            $user = $auth->guard($guard)->user();
157 3
            if ($user === null) {
158 1
                $guard = false;
159 1
            }
160 3
        }
161 3
        return $guard;
162
    }
163
164
    /**
165
     * @inheritdoc
166
     */
167 5
    public function user()
168
    {
169 5
        if (!is_null($this->user)) {
170 3
            return $this->user;
171
        }
172 5
        $user = null;
173 5
        $token = $this->getBearerToken();
174 5
        if ($token !== false) {
175 5
            $user = $this->getProvider()->retrieveById($token->getClaim('sub'));
176 5
            $claimValidation = [static::JWT_GUARD_CLAIM => $this->id];
177 5
            if (!($user instanceof SubjectContract)
178 5
                || !$token->ensureClaimValues(array_merge($user->getJWTClaimValidation(), $claimValidation))) {
179 2
                $user = null;
180 2
            }
181 5
        }
182 5
        return $this->user = $user;
183
    }
184
185
    /**
186
     * @inheritdoc
187
     */
188 12
    public function getBearerToken($isRefresh = false)
189
    {
190 12
        $token = $this->request->bearerToken();
191 12
        if (empty($token)) {
192 2
            return false;
193
        }
194 10
        $processor = $this->getProcessor();
195 10
        return $processor($token, $isRefresh);
196
    }
197
198
    /**
199
     * @inheritdoc
200
     */
201 2
    public function validate(array $credentials = [])
202
    {
203 2
        $user = $this->getProvider()->retrieveByCredentials($credentials);
204 2
        if ($this->hasValidCredentials($user, $credentials)) {
0 ignored issues
show
Bug introduced by
It seems like $user defined by $this->getProvider()->re...edentials($credentials) on line 203 can also be of type object<Illuminate\Contracts\Auth\Authenticatable>; however, Canis\Lumen\Jwt\BaseGuard::hasValidCredentials() does only seem to accept object<Canis\Lumen\Jwt\Authenticatable>|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
205 1
            return true;
206
        }
207 1
        return false;
208
    }
209
210
    /**
211
     * Determine if the user matches the credentials.
212
     *
213
     * @param  Authenticatable|null  $user
214
     * @param  array  $credentials
215
     * @return bool
216
     */
217 6
    protected function hasValidCredentials($user, $credentials)
218
    {
219 6
        return !is_null($user) && $this->getProvider()->validateCredentials($user, $credentials);
220
    }
221
222
    /**
223
     * Sets the Request
224
     *
225
     * @param Request $request
226
     */
227 1
    public function setRequest(Request $request)
228
    {
229 1
        $this->request = $request;
230 1
    }
231
232
    /**
233
     * Gets the request
234
     *
235
     * @return Request
236
     */
237 1
    public function getRequest()
238
    {
239 1
        return $this->request;
240
    }
241
242
    /**
243
     * Attempt to authenticate a user using the given credentials.
244
     *
245
     * @param  array  $credentials
246
     * @return bool|Token
247
     */
248 4
    public function attempt(array $credentials = [])
249
    {
250 4
        $user = $this->getProvider()->retrieveByCredentials($credentials);
251 4
        if ($this->hasValidCredentials($user, $credentials)) { 
0 ignored issues
show
Bug introduced by
It seems like $user defined by $this->getProvider()->re...edentials($credentials) on line 250 can also be of type object<Illuminate\Contracts\Auth\Authenticatable>; however, Canis\Lumen\Jwt\BaseGuard::hasValidCredentials() does only seem to accept object<Canis\Lumen\Jwt\Authenticatable>|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
252 3
            if (!($user instanceof SubjectContract)) {
253 1
                throw new InvalidTokenException("Unable to generate token");
254
            }
255 2
            return $this->generateToken($user);
256
        }
257 1
        return false;
258
    }
259
260
    /**
261
     * Generate a new token
262
     * 
263
     * @param  SubjectContract $user
264
     * @return Token
265
     */
266 4
    private function generateToken(SubjectContract $user)
267
    {
268 4
        $tokenGenerator = $this->getGenerator();
269 4
        $claims = $user->getJWTClaims();
270 4
        $claims['sub'] = $user->getJWTSubject();
271 4
        $claims[static::JWT_GUARD_CLAIM] = $this->id;
272 4
        if (!($token = $tokenGenerator($claims))) {
273 1
            throw new InvalidTokenException("Unable to generate token");
274
        }
275 3
        return $token;
276
    }
277
}
278