TokenGenerator::__construct()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 3
nop 2
dl 0
loc 14
rs 9.7998
c 0
b 0
f 0
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 the payload of a CSRF token.
44
     *
45
     * @param string $nonce Value used to associate a client session
46
     * @param int    $iat   The time that the token was issued, defaults to `time()`
47
     * @param int    $exp   The expiration time
48
     *
49
     * @return \stdClass
50
     */
51
    protected function generatePayload($nonce, $iat, $exp)
52
    {
53
        $payload = new \stdClass();
54
        $payload->nonce = $nonce;
55
        $payload->iat = $iat;
56
        $payload->ttl = $exp - $iat;
57
        $payload->exp = $exp;
58
59
        return $payload;
60
    }
61
62
    /**
63
     * Generate a CSRF token.
64
     *
65
     * @param string $nonce Value used to associate a client session
66
     * @param int    $iat   The time that the token was issued, defaults to `time()`
67
     * @param int    $exp   The expiration time, defaults to `$iat + $this->ttl`
68
     *
69
     * @return string
70
     *
71
     * @throws \InvalidArgumentException For invalid $iat, $exp and $nonce arguments
72
     */
73
    public function __invoke($nonce, $iat = null, $exp = null)
74
    {
75
        if ($iat === null) {
76
            $iat = time();
77
        }
78
79
        if (!is_int($iat)) {
80
            throw new \InvalidArgumentException('iat is not an integer');
81
        }
82
83
        if ($exp === null) {
84
            $exp = $iat + $this->ttl;
85
        }
86
87
        if (!is_int($exp)) {
88
            throw new \InvalidArgumentException('exp is not an integer');
89
        }
90
91
        if ($exp < $iat) {
92
            throw new \InvalidArgumentException('exp before iat');
93
        }
94
95
        if (!is_string($nonce)) {
96
            throw new \InvalidArgumentException('nonce is not an string');
97
        }
98
99
        $payload = $this->generatePayload($nonce, $iat, $exp);
100
        $payloadBase64 = $this->base64url->encode(json_encode($payload));
101
        $sign = $this->sign;
102
103
        return $payloadBase64.'.'.$sign($payloadBase64);
104
    }
105
}
106