Completed
Push — master ( 6157a8...e866d1 )
by Michael
07:36
created

TokenGenerator::__construct()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 14
rs 9.4285
cc 3
eloc 8
nc 3
nop 2
1
<?php
2
3
namespace Schnittstabil\Csrf\TokenService;
4
5
use Base64Url\Base64Url;
6
7
/**
8
 * A TokenGenerator.
9
 */
10
class TokenGenerator
11
{
12
    protected $sign;
13
    protected $ttl;
14
    protected $base64url;
15
16
    /**
17
     * Create a new TokenGenerator.
18
     *
19
     * `$ttl` is used for calculating the expiration time of the tokens, its default value (1440sec === 24min)
20
     * correspond to the default `session.gc_maxlifetime`.
21
     *
22
     * @see http://php.net/manual/en/session.configuration.php Documentation of `session.gc-maxlifetime`.
23
     *
24
     * @param callable $sign Callable used for generating the token signatures.
25
     * @param int      $ttl  Default Time to Live in seconds.
26
     */
27
    public function __construct(callable $sign, $ttl = 1440)
28
    {
29
        if (!is_int($ttl)) {
30
            throw new \InvalidArgumentException('ttl is not an integer');
31
        }
32
33
        if ($ttl <= 0) {
34
            throw new \InvalidArgumentException('ttl is non-positive');
35
        }
36
37
        $this->sign = $sign;
38
        $this->ttl = $ttl;
39
        $this->base64url = new Base64Url();
40
    }
41
42
    /**
43
     * Generate a CSRF token.
44
     *
45
     * @param int $iat The time that the token was issued, defaults to `time()`
46
     * @param int $exp The expiration time, defaults to `$iat + $this->ttl`
47
     *
48
     * @return string
49
     *
50
     * @throws \InvalidArgumentException For invalid $iat and $exp arguments.
51
     */
52
    public function __invoke($iat = null, $exp = null)
53
    {
54
        if ($iat === null) {
55
            $iat = time();
56
        }
57
58
        if (!is_int($iat)) {
59
            throw new \InvalidArgumentException('iat is not an integer');
60
        }
61
62
        if ($exp === null) {
63
            $exp = $iat + $this->ttl;
64
        }
65
66
        if (!is_int($exp)) {
67
            throw new \InvalidArgumentException('exp is not an integer');
68
        }
69
70
        if ($exp < $iat) {
71
            throw new \InvalidArgumentException('exp before iat');
72
        }
73
74
        $payload = [
75
            'iat' => $iat,
76
            'ttl' => $exp - $iat,
77
            'exp' => $exp,
78
        ];
79
80
        $payloadBase64 = $this->base64url->encode(json_encode($payload));
81
        $sign = $this->sign;
82
83
        return $payloadBase64.'.'.$sign($payloadBase64);
84
    }
85
}
86