Failed Conditions
Push — master ( 4eac43...ea568c )
by Arnold
01:44
created

Jwt::getInfo()   B

Complexity

Conditions 7
Paths 12

Size

Total Lines 27
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 7

Importance

Changes 0
Metric Value
eloc 17
dl 0
loc 27
ccs 16
cts 16
cp 1
rs 8.8333
c 0
b 0
f 0
cc 7
nc 12
nop 0
crap 7
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Jasny\Auth\Session;
6
7
use Jasny\Auth\Session\Jwt\Cookie;
8
use Jasny\Auth\Session\Jwt\CookieInterface;
9
use Jasny\Immutable;
10
use Lcobucci\JWT\Configuration;
11
12
/**
13
 * Use JSON Web Token and JSON Web Signature (RFC 7519) to store auth session info.
14
 *
15
 * @see https://github.com/lcobucci/jwt
16
 */
17
class Jwt implements SessionInterface
18
{
19
    use Immutable\With;
20
21
    protected Configuration $jwtConfig;
22
23
    protected int $ttl = 24 * 3600;
24
    protected CookieInterface $cookie;
25
26
    /**
27
     * JWT constructor.
28
     */
29 7
    public function __construct(Configuration $jwtConfig)
30
    {
31 7
        $this->jwtConfig = $jwtConfig;
32 7
        $this->cookie = new Cookie('jwt');
33 7
    }
34
35
    /**
36
     * Get a copy with a different TTL for expiry.
37
     */
38 1
    public function withTtl(int $seconds): self
39
    {
40 1
        return $this->withProperty('ttl', $seconds);
41
    }
42
43
    /**
44
     * Get a copy with custom cookie handler.
45
     */
46 7
    public function withCookie(CookieInterface $cookie): self
47
    {
48 7
        return $this->withProperty('cookie', $cookie);
49
    }
50
51
    /**
52
     * @inheritDoc
53
     */
54 4
    public function getInfo(): array
55
    {
56 4
        $jwt = $this->cookie->get();
57
58 4
        $token = $jwt !== null && $jwt !== ''
59 3
            ? $this->jwtConfig->parser()->parse($jwt)
60 4
            : null;
61
62 4
        $constraints = $this->jwtConfig->validationConstraints();
63
64
        if (
65 4
            $token === null ||
66 4
            ($constraints !== [] && !$this->jwtConfig->validator()->validate($token, ...$constraints))
67
        ) {
68 2
            return ['user' => null, 'context' => null, 'checksum' => null, 'timestamp' => null];
69
        }
70
71 2
        $timestamp = $token->headers()->get('iat');
72 2
        if (is_array($timestamp)) {
73 1
            $timestamp = new \DateTimeImmutable($timestamp['date'], new \DateTimeZone($timestamp['timezone']));
74
        }
75
76
        return [
77 2
            'user' => $token->claims()->get('user'),
0 ignored issues
show
introduced by
Call to an undefined method Lcobucci\JWT\Token::claims().
Loading history...
78 2
            'context' => $token->claims()->get('context'),
0 ignored issues
show
introduced by
Call to an undefined method Lcobucci\JWT\Token::claims().
Loading history...
79 2
            'checksum' => $token->claims()->get('checksum'),
0 ignored issues
show
introduced by
Call to an undefined method Lcobucci\JWT\Token::claims().
Loading history...
80 2
            'timestamp' => $timestamp,
81
        ];
82
    }
83
84
    /**
85
     * @inheritDoc
86
     */
87 2
    public function persist($userId, $contextId, ?string $checksum, ?\DateTimeInterface $timestamp): void
88
    {
89 2
        $builder = clone $this->jwtConfig->builder();
90
91 2
        if ($timestamp instanceof \DateTime) {
92 2
            $timestamp = \DateTimeImmutable::createFromMutable($timestamp);
93
        }
94 2
        $time = $timestamp ?? new \DateTimeImmutable();
95 2
        $expire = $time->add(new \DateInterval("PT{$this->ttl}S"));
0 ignored issues
show
introduced by
Call to an undefined method DateTimeInterface::add().
Loading history...
Bug introduced by
The method add() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

95
        /** @scrutinizer ignore-call */ 
96
        $expire = $time->add(new \DateInterval("PT{$this->ttl}S"));

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
96
97
        $builder
98 2
            ->withClaim('user', $userId)
99 2
            ->withClaim('context', $contextId)
100 2
            ->withClaim('checksum', $checksum)
101 2
            ->issuedAt($time)
0 ignored issues
show
introduced by
Parameter #1 $issuedAt of method Lcobucci\JWT\Builder::issuedAt() expects DateTimeImmutable, DateTimeInterface given.
Loading history...
Bug introduced by
It seems like $time can also be of type null; however, parameter $issuedAt of Lcobucci\JWT\Builder::issuedAt() does only seem to accept DateTimeImmutable, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

101
            ->issuedAt(/** @scrutinizer ignore-type */ $time)
Loading history...
102 2
            ->expiresAt($expire);
103
104 2
        if ($timestamp !== null) {
105 2
            $builder->withHeader('iat', $timestamp);
106
        }
107
108 2
        $this->cookie->set(
109 2
            $builder->getToken($this->jwtConfig->signer(), $this->jwtConfig->signingKey())->toString(),
110 2
            $expire->getTimestamp()
111
        );
112 2
    }
113
114
    /**
115
     * @inheritDoc
116
     */
117 1
    public function clear(): void
118
    {
119 1
        $this->cookie->clear();
120 1
    }
121
}
122