Completed
Push — develop ( 574df4...10ba76 )
by Wisoot
06:15
created

JwtService::wipeUserTokens()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
namespace WWON\JwtGuard;
4
5
use Firebase\JWT\ExpiredException;
6
use Firebase\JWT\JWT;
7
use Illuminate\Contracts\Auth\Authenticatable;
8
use Illuminate\Support\Facades\Config;
9
use WWON\JwtGuard\Contract\TokenManager;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, WWON\JwtGuard\TokenManager.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
10
use WWON\JwtGuard\Exceptions\InaccessibleException;
11
use WWON\JwtGuard\Exceptions\InvalidTokenException;
12
use WWON\JwtGuard\Exceptions\MalformedException;
13
use WWON\JwtGuard\Exceptions\TokenExpiredException;
14
use WWON\JwtGuard\Exceptions\UnRefreshableException;
15
16
class JwtService
17
{
18
19
    /**
20
     * @var string
21
     */
22
    private $key;
23
24
    /**
25
     * @var TokenManager
26
     */
27
    protected $tokenManager;
28
29
    /**
30
     * JwtService constructor
31
     *
32
     * @param TokenManager $tokenManager
33
     */
34
    public function __construct(TokenManager $tokenManager)
35
    {
36
        $this->key = Config::get('jwt.secret');
37
        $this->tokenManager = $tokenManager;
38
39
        JWT::$leeway = Config::get('jwt.leeway');
40
    }
41
42
    /**
43
     * getTokenForUser method
44
     *
45
     * @param Authenticatable $user
46
     * @param bool $refreshable
47
     * @return string
48
     */
49
    public function getTokenForUser(Authenticatable $user, $refreshable = false)
50
    {
51
        $claim = new Claim([
52
            'sub' => $user->getAuthIdentifier(),
53
            'refresh' => $refreshable
54
        ]);
55
56
        return $this->getTokenForClaim($claim);
57
    }
58
59
    /**
60
     * getUserIdFromToken method
61
     *
62
     * @param string $token
63
     * @return mixed
64
     * @throws InaccessibleException
65
     * @throws MalformedException
66
     * @throws TokenExpiredException
67
     * @throws InvalidTokenException
68
     */
69
    public function getUserIdFromToken($token)
70
    {
71
        $claim = $this->getClaimFromToken($token);
72
73
        $claim->validateAccessible();
74
75
        if (!$this->tokenManager->check($claim)) {
76
            throw new InvalidTokenException;
77
        }
78
79
        return $claim->sub;
80
    }
81
82
    /**
83
     * refreshToken method
84
     *
85
     * @param string $token
86
     * @return string
87
     * @throws MalformedException
88
     * @throws TokenExpiredException
89
     * @throws UnRefreshableException
90
     */
91
    public function refreshToken($token)
92
    {
93
        $claim = $this->getClaimFromToken($token);
94
        
95
        if (empty($claim->refresh)) {
96
            throw new UnRefreshableException;
97
        }
98
99
        $this->tokenManager->remove($claim);
100
101
        $newClaim = new Claim([
102
            'sub' => $claim->sub
103
        ]);
104
105
        return $this->getTokenForClaim($newClaim);
106
    }
107
108
    /**
109
     * invalidateToken method
110
     *
111
     * @param string $token
112
     * @throws MalformedException
113
     * @throws TokenExpiredException
114
     * @throws UnRefreshableException
115
     */
116
    public function invalidateToken($token)
117
    {
118
        $claim = $this->getClaimFromToken($token);
119
120
        $this->tokenManager->remove($claim);
121
    }
122
123
    /**
124
     * wipeUserTokens method
125
     *
126
     * @param Authenticatable $user
127
     */
128
    public function wipeUserTokens(Authenticatable $user)
129
    {
130
        $this->tokenManager->removeAll($user->getAuthIdentifier());
131
    }
132
133
    /**
134
     * getTokenForUser method
135
     *
136
     * @param Claim $claim
137
     * @return string
138
     */
139
    protected function getTokenForClaim(Claim $claim)
140
    {
141
        $token = JWT::encode($claim->toArray(), $this->key, Config::get('jwt.algo'));
142
        $this->tokenManager->add($claim);
143
144
        return $token;
145
    }
146
147
    /**
148
     * getClaimFromToken method
149
     *
150
     * @param $token
151
     * @return Claim
152
     * @throws MalformedException
153
     * @throws TokenExpiredException
154
     */
155
    protected function getClaimFromToken($token)
156
    {
157
        try {
158
            $payload = JWT::decode($token, $this->key, [
159
                'HS256', 'HS384', 'HS512', 'RS256'
160
            ]);
161
162
        } catch (ExpiredException $e) {
163
            throw new TokenExpiredException($e->getMessage(), $e->getCode(), $e);
164
        }
165
166
        return new Claim((array) $payload);
167
    }
168
169
}