headerAuth   A
last analyzed

Complexity

Total Complexity 42

Size/Duplication

Total Lines 245
Duplicated Lines 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
eloc 104
c 4
b 0
f 0
dl 0
loc 245
rs 9.0399
wmc 42

8 Methods

Rating   Name   Duplication   Size   Complexity  
B isGrantRequest() 0 27 7
A authorizationHeaders() 0 12 4
A __construct() 0 2 1
C accessCredentialHeaders() 0 61 14
A hasBearerValue() 0 14 4
A hasBearerToken() 0 14 4
B accessRefreshHeaders() 0 42 6
A setUnauthorised() 0 13 2

How to fix   Complexity   

Complex Class

Complex classes like headerAuth often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use headerAuth, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * ==================================
4
 * Responsible PHP API
5
 * ==================================
6
 *
7
 * @link Git https://github.com/vince-scarpa/responsibleAPI.git
8
 *
9
 * @api Responible API
10
 * @package responsible\core\headers
11
 *
12
 * @author Vince scarpa <[email protected]>
13
 *
14
 */
15
namespace responsible\core\headers;
16
17
use responsible\core\server;
18
use responsible\core\encoder;
19
use responsible\core\exception;
20
use responsible\core\helpers\help as helper;
21
use responsible\core\user;
22
23
class headerAuth extends header
24
{
25
    use \responsible\core\traits\optionsTrait;
26
27
    /**
28
     * [__construct]
29
     */
30
    public function __construct()
31
    {}
32
33
    /**
34
     * [authorizationHeaders Scan for "Authorization" header]
35
     * @return string|array [mixed: string / error]
36
     */
37
    public function authorizationHeaders($skipError = false)
38
    {
39
        if ($grant = $this->isGrantRequest()) {
40
            return $grant;
41
        }
42
43
        if ($clientToken = $this->hasBearerToken()) {
44
            return $clientToken;
45
        }
46
47
        if (!$skipError) {
48
            $this->setUnauthorised();
49
        }
50
    // @codeCoverageIgnoreStart
51
    }
52
    // @codeCoverageIgnoreEnd
53
54
    /**
55
     * [hasBearerValue Check if Authorization headers has Bearer value]
56
     * @throws Exception
57
     *         Unauthorised
58
     * @return boolean
59
     */
60
    private function hasBearerValue()
61
    {
62
        $auth_headers = $this->getHeaders();
63
64
        if (isset($auth_headers["Authorization"]) && !empty($auth_headers["Authorization"])) {
65
66
            list($type, $clientToken) = explode(" ", $auth_headers["Authorization"], 2);
67
68
            if (strcasecmp(trim($type), "Bearer") == 0) {
69
                return true;
70
            }
71
        }
72
73
        return false;
74
    }
75
76
    /**
77
     * [hasBearerToken Check if bearer token is present]
78
     * @return string|null
79
     */
80
    public function hasBearerToken()
81
    {
82
        $auth_headers = $this->getHeaders();
83
84
        if ($this->hasBearerValue()) {
85
86
            list($type, $clientToken) = explode(" ", $auth_headers["Authorization"], 2);
87
88
            if (strcasecmp(trim($type), "Bearer") == 0 && !empty($clientToken)) {
89
                return $clientToken;
90
            }
91
        }
92
93
        return;
94
    }
95
96
    /**
97
     * Check if the request is a token grant
98
     * @return array|boolean
99
     */
100
    public function isGrantRequest()
101
    {
102
        $auth_headers = $this->getHeaders();
103
        $helper = new helper;
104
105
        if (isset($auth_headers["Authorization"]) && !empty($auth_headers["Authorization"])) {
106
            if ($grantType = $helper->checkVal($_REQUEST, 'grant_type')) {
107
108
                $refreshToken = false;
109
110
                if ($grantType == 'client_credentials') {
111
                    $refreshToken = $this->accessCredentialHeaders($auth_headers);
112
                }
113
114
                if ($grantType == 'refresh_token') {
115
                    $refreshToken = $this->accessRefreshHeaders($auth_headers);
116
                }
117
118
                if ($refreshToken) {
119
                    return [
120
                        'client_access_request' => $refreshToken,
121
                    ];
122
                }
123
            }
124
        }
125
126
        return false;
127
    }
128
129
    /**
130
     * [accessRefreshHeaders description]
131
     * @return string|array [mixed: string / error]
132
     */
133
    private function accessRefreshHeaders($auth_headers)
134
    {
135
        list($type, $clientToken) = explode(" ", $auth_headers["Authorization"], 2);
136
137
        $server = new server([], $this->getOptions());
138
        $mockTest = $server->isMockTest();
139
140
        // @codeCoverageIgnoreStart
141
        if (strcasecmp($type, "Bearer") == 0 && !empty($clientToken) && !$mockTest) {
142
143
            $user = new user\user;
144
            $account = $user
145
                ->setOptions($this->options)
146
                ->load(
147
                    $clientToken,
148
                    array(
149
                        'loadBy' => 'refresh_token',
150
                        'getJWT' => true,
151
                        'authorizationRefresh' => true,
152
                    )
153
                );
154
155
            if (empty($account)) {
156
                $this->setUnauthorised();
157
            }
158
159
            $tokens = [
160
                'token' => $account['JWT'],
161
                'refresh_token' => $account['refreshToken']['token'],
162
            ];
163
164
            $account['refreshToken'] = $tokens;
165
166
            return $account;
167
168
        } else {
169
            if ($mockTest) {
170
                return [
171
                    'mock_access' => true
172
                ];
173
            }
174
            $this->setUnauthorised();
175
        }
176
    }
177
    // @codeCoverageIgnoreEnd
178
179
    /**
180
     * [accessCredentialHeaders Check if the credentials are correct]
181
     * @param  array $auth_headers
182
     * @return string|array [mixed: string / error]
183
     */
184
    private function accessCredentialHeaders($auth_headers)
185
    {
186
        $cipher = new encoder\cipher;
187
188
        list($type, $clientCredentials) = explode(" ", $auth_headers["Authorization"], 2);
189
190
        if (strcasecmp($type, "Basic") == 0 && !empty($clientCredentials)) {
191
            $credentails = explode('/', $clientCredentials);
192
            if (!empty($credentails) && is_array($credentails)) {
193
                $credentails = explode(':', $cipher->decode($clientCredentials));
194
195
                $server = new server([], $this->getOptions());
196
                $mockTest = $server->isMockTest();
197
198
                if ($mockTest &&
199
                    (in_array('mockusername', $credentails) && in_array('mockpassword', $credentails)) 
200
                ) {
201
                    return [
202
                        'uid' => -1,
203
                        'account_id' => 0,
204
                        'access_token' => '',
205
                        'refreshToken' => [
206
                            'refresh_token' => '',
207
                        ]
208
                    ];
209
                }
210
211
                // @codeCoverageIgnoreStart
212
                if (!empty($credentails) && is_array($credentails) && sizeof($credentails) == 2 
213
                    && !$mockTest
214
                ) {
215
                    $user = new user\user;
216
                    $user->setAccountID($credentails[0]);
217
218
                    $account = $user
219
                        ->setOptions($this->options)
220
                        ->load(
221
                            $credentails[0],
222
                            array(
223
                                'loadBy' => 'account_id',
224
                                'getJWT' => true,
225
                                'authorizationRefresh' => true,
226
                            )
227
                        );
228
229
                    $tokens = [
230
                        'token' => $account['JWT'],
231
                        'refresh_token' => $account['refreshToken']['token'],
232
                    ];
233
234
                    $account['refreshToken'] = $tokens;
235
236
                    if (!empty($account)) {
237
                        if (strcasecmp($account['secret'], $credentails[1]) == 0) {
238
                            return $account;
239
                        }
240
                    }
241
                }
242
            }
243
        } else {
244
            $this->setUnauthorised();
245
        }
246
    }
247
    // @codeCoverageIgnoreEnd
248
249
    /**
250
     * [unauthorised Set an unauthorised header]
251
     * @throws Exception
252
     *         UNAUTHORIZED 401
253
     * @return void
254
     */
255
    public function setUnauthorised()
256
    {
257
        $corsAllowed = ($this->getOptions()['cors']) ?? false;
258
        $isCorsRequest = ($_SERVER['HTTP_ORIGIN']) ?? false;
259
        $this->setHeaders($corsAllowed&&$isCorsRequest);
260
261
        $this->setHeader('HTTP/1.1', array(
262
            'Unauthorized',
263
        ), 401);
264
        
265
        (new exception\errorException)
266
            ->setOptions($this->getOptions())
267
            ->error('UNAUTHORIZED');
268
    // @codeCoverageIgnoreStart
269
    }
270
    // @codeCoverageIgnoreEnd
271
}
272