JwtService   A
last analyzed

Complexity

Total Complexity 21

Size/Duplication

Total Lines 135
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 12

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 21
lcom 1
cbo 12
dl 0
loc 135
ccs 60
cts 60
cp 1
rs 10
c 0
b 0
f 0

14 Methods

Rating   Name   Duplication   Size   Complexity  
A setAudience() 0 5 1
A getAudience() 0 4 1
A getEncryption() 0 4 1
A setExpire() 0 5 1
A encode() 0 5 1
A createToken() 0 18 3
A __construct() 0 7 1
A decode() 0 4 1
A verify() 0 16 4
A getData() 0 10 2
A getEmptyToken() 0 4 1
A setPayloadClaim() 0 10 2
A getClaimFactory() 0 4 1
A getLib() 0 4 1
1
<?php
2
declare(strict_types=1);
3
4
namespace PTS\JwtService;
5
6
use Emarref\Jwt\Algorithm\AlgorithmInterface;
7
use Emarref\Jwt\Encryption\EncryptionInterface;
8
use Emarref\Jwt\Jwt;
9
use Emarref\Jwt\Token;
10
use Emarref\Jwt\Claim;
11
use Emarref\Jwt\Claim\Factory as ClaimFactory;
12
use Emarref\Jwt\Encryption\Factory as EncryptionFactory;
13
use Emarref\Jwt\Verification\Context as VerificationContext;
14
15
class JwtService
16
{
17
    /** @var Jwt */
18
    protected $lib;
19
    /** @var ClaimFactory */
20
    protected $claimFactory;
21
    /** @var EncryptionInterface */
22
    protected $encryption;
23
    /** @var string|null */
24
    protected $audience;
25
    /** @var int */
26
    protected $expireSec = 0;
27
    /** @var Token */
28
    protected $emptyToken;
29
30 13
    public function __construct(AlgorithmInterface $algorithm)
31
    {
32 13
        $this->claimFactory = new ClaimFactory;
33 13
        $this->lib = new Jwt;
34 13
        $this->encryption = EncryptionFactory::create($algorithm);
35 13
        $this->emptyToken = new Token;
36 13
    }
37
38 8
    public function setAudience(string $audience): self
39
    {
40 8
        $this->audience = $audience;
41 8
        return $this;
42
    }
43
44 7
    public function getAudience(): ?string
45
    {
46 7
        return $this->audience;
47
    }
48
49 1
    public function getEncryption(): EncryptionInterface
50
    {
51 1
        return $this->encryption;
52
    }
53
54 3
    public function setExpire(int $sec): self
55
    {
56 3
        $this->expireSec = $sec;
57 3
        return $this;
58
    }
59
60 1
    public function encode(array $payload = []): string
61
    {
62 1
        $token = $this->createToken($payload);
63 1
        return $this->getLib()->serialize($token, $this->getEncryption());
64
    }
65
66 4
    public function createToken(array $payload): Token
67
    {
68 4
        $token = $this->getEmptyToken();
69 4
        $this->setPayloadClaim($payload, $token);
70
71 4
        $now = time();
72 4
        $token->addClaim(new Claim\IssuedAt($now));
73 4
        $token->addClaim(new Claim\NotBefore($now));
74
75 4
        if ($this->getAudience()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->getAudience() of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
76 2
            $token->addClaim(new Claim\Audience($this->getAudience()));
77
        }
78 4
        if ($this->expireSec > 0) {
79 2
            $token->addClaim(new Claim\Expiration($now + $this->expireSec));
80
        }
81
82 4
        return $token;
83
    }
84
85 1
    public function decode(string $serializedToken): Token
86
    {
87 1
        return $this->getLib()->deserialize($serializedToken);
88
    }
89
90
    /**
91
     * @param Token $token
92
     * @param VerificationContext|null $verificationContext
93
     *
94
     * @throws VerifyTokenException
95
     */
96 6
    public function verify(Token $token, VerificationContext $verificationContext = null): void
97
    {
98 6
        if (null === $verificationContext) {
99 3
            $verificationContext = new VerificationContext($this->getEncryption());
100
        }
101
102 6
        if ($this->getAudience()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->getAudience() of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
103 4
            $verificationContext->setAudience($this->getAudience());
104
        }
105
106
        try {
107 6
            $this->getLib()->verify($token, $verificationContext);
108 4
        } catch (\Exception $exception) {
109 4
            throw new VerifyTokenException('Token did not pass the verification', $exception->getCode(), $exception);
110
        }
111 2
    }
112
113 1
    public function getData(Token $token): array
114
    {
115 1
        $data = [];
116 1
        foreach ($token->getPayload()->getClaims()->getIterator() as $property) {
117 1
            $name = $property->getName();
118 1
            $data[$name] = $property->getValue();
119
        }
120
121 1
        return $data;
122
    }
123
124 1
    protected function getEmptyToken(): Token
125
    {
126 1
        return clone $this->emptyToken;
127
    }
128
129 3
    protected function setPayloadClaim(array $payload, Token $token): void
130
    {
131 3
        $claimFactory = $this->getClaimFactory();
132
133 3
        foreach ($payload as $name => $value) {
134 3
            $claim = $claimFactory->get($name);
135 3
            $claim->setValue($value);
136 3
            $token->addClaim($claim);
137
        }
138 3
    }
139
140 1
    protected function getClaimFactory(): ClaimFactory
141
    {
142 1
        return $this->claimFactory;
143
    }
144
145 1
    protected function getLib(): Jwt
146
    {
147 1
        return $this->lib;
148
    }
149
}
150