CSRF::checkExpired()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 9
nc 2
nop 1
dl 0
loc 14
rs 9.9666
c 0
b 0
f 0
1
<?php
2
namespace ScienceHook\Security\CSRF;
3
4
use ScienceHook\Security\CSRF\Exception as Issues;
5
use ScienceHook\Security\CSRF\Dependency\SessionHandler\SessionHandler;
6
7
/**
8
 * Class CSRF
9
 *
10
 * @package ScienceHook\Security\CSRF
11
 * @author Kshitij Kumar
12
 */
13
class CSRF
14
{
15
    /**
16
     * Stores form_name to store CSRF token value in SESSION
17
     *
18
     * @var string
19
     */
20
    private $form_name;
21
22
    /**
23
     * Byte length for random_bytes
24
     *
25
     * @var int
26
     */
27
    private $length;
28
29
    /**
30
     * SessionHandler object to manage SESSION operations
31
     *
32
     * @var SessionHandler
33
     */
34
    private $session_handler;
35
36
    /**
37
     * Token prefix for Form
38
     *
39
     * @var string
40
     */
41
    private $token_prefix;
42
43
    /**
44
     * Time token prefix
45
     *
46
     * @var string
47
     */
48
    private $time_token_prefix;
49
50
    /**
51
     * CSRF constructor
52
     *
53
     * @param  string $form_name         Value for form_name param
54
     * @param  int $length               Byte length value for length param
55
     * @param string $token_prefix       User preferred token prefix
56
     * @param string $time_token_prefix  User preferred time token prefix
57
     */
58
    public function __construct(
59
        string $form_name,
60
        int $length = 32,
61
        string $token_prefix = 'token_',
62
        string $time_token_prefix = 'token_time_'
63
    ) {
64
        $this->form_name = $form_name;
65
        $this->length = $length;
66
        $this->token_prefix = $token_prefix;
67
        $this->time_token_prefix = $time_token_prefix;
68
        $this->session_handler = new SessionHandler();
69
    }
70
71
    /**
72
     * Creates SESSION with token and time token value
73
     *
74
     * @throws Issues\SessionNotActiveException
75
     * @throws \Exception
76
     * @throws \TypeError
77
     * @throws \Error
78
     */
79
    public function createToken()
80
    {
81
        $this->session_handler->setSessionValue(
82
            $this->form_name,
83
            $this->token_prefix,
84
            $this->time_token_prefix,
85
            $this->length
86
        );
87
    }
88
89
    /**
90
     * Returns token value (Not Time Token) from SESSION
91
     *
92
     * @return string
93
     * @throws Issues\SessionNotActiveException
94
     * @throws Issues\SessionValueNotSet
95
     */
96
    private function getTokenValue(): string
97
    {
98
        return $this->session_handler->getSessionValue(
99
            $this->form_name,
100
            $this->token_prefix
101
        );
102
    }
103
104
    /**
105
     * Returns time token value from SESSION
106
     *
107
     * @return string
108
     * @throws Issues\SessionNotActiveException
109
     * @throws Issues\SessionValueNotSet
110
     */
111
    private function getTimeTokenValue(): string
112
    {
113
        return $this->session_handler->getSessionValue(
114
            $this->form_name,
115
            $this->time_token_prefix
116
        );
117
    }
118
119
    /**
120
     * @param string $token    Token passed in form validation for verification
121
     * @param int $time        Token expiry time
122
     * @return bool
123
     * @throws Issues\SessionNotActiveException
124
     * @throws Issues\SessionValueNotSet
125
     */
126
    public function checkValid(string $token, int $time = 300): bool
127
    {
128
        // Compares hash values of token, not time one
129
        $is_valid = hash_equals(
130
            $token,
131
            $this->session_handler->getSessionValue(
132
                $this->form_name,
133
                $this->token_prefix
134
            )
135
        );
136
137
        // Checks if the token is expired
138
        $is_expired = $this->checkExpired($time);
139
        return $is_valid && !$is_expired;
140
    }
141
142
    /**
143
     * Checks token expiry based on user's time input in checkValid()
144
     *
145
     * @param int $time
146
     * @return bool
147
     * @throws Issues\SessionNotActiveException
148
     * @throws Issues\SessionValueNotSet
149
     */
150
    private function checkExpired(int $time): bool
151
    {
152
        $token_age = time() - $this->getTimeTokenValue();
153
154
        if ($token_age >= $time) {
155
            // Deletes the tokens in session for this person
156
            $this->session_handler->unsetSession(
157
                $this->form_name,
158
                $this->token_prefix,
159
                $this->time_token_prefix
160
            );
161
            return true;
162
        } else {
163
            return false;
164
        }
165
    }
166
167
    /**
168
     * Creates hidden field for forms
169
     *
170
     * @return string
171
     * @throws Issues\SessionNotActiveException
172
     * @throws Issues\SessionValueNotSet
173
     */
174
    public function createHiddenField(): string
175
    {
176
        // creates the HTML for a hidden text field with the token
177
        // form_name is being passed along with the token
178
        // You can override this method to include more parameters as per your needs
179
        // or in case of inconsistent token prefixes or byte length for random_bytes
180
181
        $field = '<input type="hidden" id="token" name="token" value="' . $this->form_name . ':' .
182
            $this->getTokenValue() . '">';
183
        return $field;
184
    }
185
186
    /**
187
     * Echos token expiry message
188
     */
189
    public function showInvalidError()
190
    {
191
        echo '* Your token has expired. Please refresh the page and try again.';
192
    }
193
}
194