Completed
Pull Request — master (#2)
by René
04:42
created

Cookie::getTokenString()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 22
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6
Metric Value
dl 0
loc 22
ccs 0
cts 9
cp 0
rs 9.2
cc 2
eloc 9
nc 2
nop 0
crap 6
1
<?php
2
declare(strict_types = 1);
3
4
namespace Zortje\MVC\Storage\Cookie;
5
6
use Lcobucci\JWT\Builder;
7
use Lcobucci\JWT\Claim;
8
use Lcobucci\JWT\Parser;
9
use Lcobucci\JWT\Signer\Hmac\Sha256;
10
use Lcobucci\JWT\ValidationData;
11
use Zortje\MVC\Configuration\Configuration;
12
use Zortje\MVC\Storage\Cookie\Exception\CookieUndefinedIndexException;
13
14
/**
15
 * Class Cookie
16
 *
17
 * @package Zortje\MVC\Storage
18
 */
19
class Cookie
20
{
21
22
    const ISSUER = 'zortje/mvc';
23
24
    /**
25
     * @var Configuration
26
     */
27
    protected $configuration;
28
29
    /**
30
     * @var string[] Internal cookie values
31
     */
32
    protected $values = [];
33
34
    /**
35
     * Cookie constructor.
36
     *
37
     * @param Configuration $configuration Configuration
38
     * @param string        $token         JWT string
39
     */
40 1
    public function __construct(Configuration $configuration, string $token = '')
41
    {
42 1
        $this->configuration = $configuration;
43 1
        $this->values        = $this->parseAndValidateToken($token);
44 1
    }
45
46
    /**
47
     * Set value in cookie
48
     *
49
     * @param string $key   Cookie key
50
     * @param string $value Cookie value
51
     */
52 2
    public function set(string $key, string $value)
53
    {
54 2
        $this->values[$key] = $value;
55 2
    }
56
57
    /**
58
     * Check if value for key exists in cookie
59
     *
60
     * @param string $key Cookie key
61
     *
62
     * @return bool TRUE if key exists, otherwise FALSE
63
     */
64
    public function exists(string $key)
65
    {
66
        return isset($this->values[$key]);
67
    }
68
69
    /**
70
     * Remove value for key in cookie
71
     *
72
     * @param string $key Cookie key
73
     */
74
    public function remove(string $key)
75
    {
76
        unset($this->values[$key]);
77
    }
78
79
    /**
80
     * Get value from cookie
81
     *
82
     * @param string $key Cookie key
83
     *
84
     * @return string Cookie value
85
     *
86
     * @throws CookieUndefinedIndexException
87
     */
88 1
    public function get(string $key): string
89
    {
90 1
        if (isset($this->values[$key]) === false) {
91
            throw new CookieUndefinedIndexException([$key]);
92
        }
93
94 1
        return $this->values[$key];
95
    }
96
97
    /**
98
     * @return string JWT string
99
     */
100
    public function getTokenString(): string
101
    {
102
        /**
103
         * Build Token
104
         */
105
        $builder = (new Builder());
106
        $builder->setIssuer(self::ISSUER);
107
        $builder->setExpiration((new \DateTime($this->configuration->get('Cookie.TTL')))->getTimestamp());
108
109
        foreach ($this->values as $key => $value) {
110
            $builder->set($key, $value);
111
        }
112
113
        /**
114
         * Sign and generate new token
115
         */
116
        $builder->sign(new Sha256(), $this->configuration->get('Cookie.Signer.Key'));
117
118
        $token = $builder->getToken();
119
120
        return (string)$token;
121
    }
122
123
    /**
124
     * Validates token for cookie and returns values if valid
125
     *
126
     * @param string $token
127
     *
128
     * @return array
129
     */
130
    protected function parseAndValidateToken(string $token)
131
    {
132
        try {
133
            $token = (new Parser())->parse($token);
134
135
            // @todo How to test: It will use the current time to validate (iat, nbf and exp)
136
            $data = new ValidationData();
137
            $data->setIssuer(self::ISSUER);
138
139
            $values = [];
140
141
            if ($token->validate($data) && $token->verify(new Sha256(),
142
                    $this->configuration->get('Cookie.Signer.Key'))
143
            ) {
144
                /**
145
                 * @var Claim $claim
146
                 */
147
                $ignored = array_fill_keys(['iss', 'exp'], true);
148
149
                foreach ($token->getClaims() as $claim) {
150
                    if (isset($ignored[$claim->getName()])) {
151
                        continue;
152
                    }
153
154
                    $values[$claim->getName()] = $claim->getValue();
155
                }
156
            }
157
158
            return $values;
159
        } catch (\InvalidArgumentException $e) {
160
            return [];
161
        }
162
    }
163
}
164