Completed
Push — master ( cdb642...5a9031 )
by Terrence
13:58
created

index-functions.php ➔ verifyUserCodeParam()   F

Complexity

Conditions 23
Paths 80

Size

Total Lines 100

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 23
nc 80
nop 0
dl 0
loc 100
rs 3.3333
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * This file contains functions called by index-site.php. The index-site.php
5
 * file should include this file with the following statement at the top:
6
 *
7
 * require_once __DIR__ . '/index-functions.php';
8
 */
9
10
use CILogon\Service\Util;
11
use CILogon\Service\Content;
12
use CILogon\Service\DBService;
13
use CILogon\Service\Loggit;
14
15
/**
16
 * printLogonPage
17
 *
18
 * This function first checks if the user_code has been entered and
19
 * matching client registration information has been found. If not, then go
20
 * to printUserCodePage instead. Otherwise, print out the HTML for the
21
 * "Select an Identity Provider" page along with the client registration
22
 * info.
23
 */
24
function printLogonPage()
0 ignored issues
show
Best Practice introduced by
The function printLogonPage() has been defined more than once; this definition is ignored, only the first definition in authorize/index-functions.php (L22-52) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
25
{
26
    if (!verifyUserCodeParam()) {
27
        printUserCodePage();
28
    } else {
29
        $log = new Loggit();
30
        $log->info('Welcome page hit.');
31
32
        Content::printHeader(
33
            'Welcome To The CILogon Device Authorization Service'
34
        );
35
36
        Content::printOIDCConsent();
0 ignored issues
show
Bug introduced by
The method printOIDCConsent() does not seem to exist on object<CILogon\Service\Content>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
37
        Content::printWAYF(true, true);
0 ignored issues
show
Unused Code introduced by
The call to Content::printWAYF() has too many arguments starting with true.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
38
        Content::printFooter();
39
    }
40
}
41
42
/**
43
 * printUserCodePage
44
 *
45
 * If the user has not yet entered a user_code, or if the previously entered
46
 * user_code has expired or is not found, print out a form to prompt the
47
 * user to enter the device user_code.
48
 */
49
function printUserCodePage()
50
{
51
    $log = new Loggit();
52
    $log->info('User code page hit.');
53
54
    Content::printHeader(
55
        'Welcome To The CILogon Device Authorization Service'
56
    );
57
    Content::printCollapseBegin(
58
        'usercodedefault',
59
        'CILogon Device Flow User Code',
60
        false
61
    );
62
63
    // Check for any previously generated error message
64
    $user_code_error_msg = Util::getSessionVar('user_code_error_msg');
65
    Util::unsetSessionVar('user_code_error_msg');
66
    if (strlen($user_code_error_msg) > 0) {
67
        echo '
68
            <div class="alert alert-danger alert-dismissable fade show" role="alert">';
69
        echo $user_code_error_msg;
70
        echo '
71
              <button type="button" class="close" data-dismiss="alert"
72
                      aria-label="Close">
73
                <span aria-hidden="true">&times;</span>
74
              </button>
75
            </div>';
76
    }
77
78
    echo '
79
      <div class="card-body px-5">
80
        <div class="card-text my-2">
81
          Please enter the user code displayed on your device.
82
          If you do not have a user code, please proceed to the main
83
          <a href="..">CILogon site</a>.
84
        </div> <!-- end row -->
85
    ';
86
87
    Content::printFormHead();
88
89
    echo '
90
        <div class="form-group col-lg-6 offset-lg-3 col-md-8 offset-md-2 col-sm-10 offset-sm-1 mt-3">
91
          <label for="user-code">Enter User Code</label>
92
          <div class="form-row">
93
            <div class="col-11">
94
              <input type="text" name="user_code" id="user-code"
95
              required="required" autocomplete="off" maxlength="40"
96
              class="form-control upper" aria-describedby="user-code-help"
97
              oninput="this.value=this.value.replace(/[^a-zA-Z0-9\-\s\_]/,\'\'); upperCaseF(this);"
98
              title="User code is alphanumeric"/>
99
              <div class="invalid-tooltip">
100
                Please enter a valid user code.
101
              </div>
102
            </div>
103
          </div>
104
          <div class="form-row">
105
            <div class="col-11">
106
              <small id="user-code-help" class="form-text text-muted">
107
                Enter the user code displayed on your device.
108
              </small>
109
            </div>
110
          </div>
111
        </div> <!-- end form-group -->
112
113
        <div class="form-group">
114
          <div class="form-row align-items-center">
115
            <div class="col text-center">
116
              <input type="submit" name="submit"
117
              class="btn btn-primary submit"
118
              value="Enter User Code"/>
119
            </div>
120
          </div>
121
        </div> <!-- end form-group -->
122
123
        </form>
124
      </div> <!-- end card-body-->';
125
126
    Content::printCollapseEnd();
127
    Content::printFooter();
128
}
129
130
/**
131
 * printMainPage
132
 *
133
 * This is the page the user is redirected to after successfully logging in
134
 * with their chosen identity provider OR when the user clicks the 'Cancel'
135
 * button to deny the device authorization grant flow. When the 'Cancel'
136
 * button is clicked, a PHP session variable 'user_code_denied' is set. In
137
 * either case, if the PHP session contains the user_code entered by the
138
 * user, the userCodeApproved dbService method is called to let the OA4MP
139
 * service know that the user has approved/denied use of the user_code.
140
 */
141
function printMainPage()
0 ignored issues
show
Best Practice introduced by
The function printMainPage() has been defined more than once; this definition is ignored, only the first definition in authorize/index-functions.php (L126-222) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
142
{
143
    $log = new Loggit();
144
145
    // If user_code_denied is set (by clicking 'Cancel') then set approved
146
    // to zero when calling userCodeApproved.
147
    $user_code_approved = 1; // Assume user approved use of the user_code
148
    if (strlen(Util::getSessionVar('user_code_denied')) > 0) {
149
        Util::unsetSessionVar('user_code_denied');
150
        $user_code_approved = 0;
151
    }
152
153
    // Check the PHP session for the user_code entered by the user
154
    $clientparams = json_decode(Util::getSessionVar('clientparams'), true);
155
    Util::unsetSessionVar('clientparams');
156
    $user_code = @$clientparams['user_code'];
157
158
    $errstr = '';
159
    if (strlen($user_code) > 0) {
160
        $log->info('Calling userCodeApproved dbService method...');
161
        $dbs = new DBService();
162
        if (
163
            ($dbs->userCodeApproved($user_code, $user_code_approved)) &&
0 ignored issues
show
Bug introduced by
The method userCodeApproved() does not seem to exist on object<CILogon\Service\DBService>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
164
            (!($dbs->status & 1))
165
        ) { // STATUS_OK codes are even
166
            // SUCCESSFULLY told database about decision to approve/deny
167
        } else { // STATUS_ERROR code returned
168
            // There was a problem with the user_code
169
            $errstr = 'Error confirming user code.'; // Generic error message
170
            if (!is_null($dbs->status)) {
171
                $errstr = array_search($dbs->status, DBService::$STATUS);
172
                // Customize error messages for Device Authz Grant flow
173
                if ($dbs->status == 0x10001) {
174
                    $errstr = 'Error confirming user code: Code not found. ' .
175
                        'This can happen when the user code has expired and ' .
176
                        'is no longer avaiable in the system.';
177
                } elseif ($db->status == 0x10003) {
0 ignored issues
show
Bug introduced by
The variable $db does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
178
                    $errstr = 'Error confirming user code: Code expired. ' .
179
                        'Please return to your device and start a new request.';
180
                }
181
            }
182
        }
183
    } else { // No user_code in PHP session - weird error!
184
        $errstr = 'Error confirming user code: Code not found. ' .
185
            'Please enable cookies in your web browser.';
186
    }
187
188
    $log->info('User Code Verified page hit.');
189
190
    Content::printHeader('User Code Approval');
191
    Content::printCollapseBegin(
192
        'usercodeapproval',
193
        'CILogon User Code Verification',
194
        false
195
    );
196
197
    // Check for any previously generated error message
198
    if (strlen($errstr) > 0) {
199
        echo '
200
            <div class="alert alert-danger show" role="alert">';
201
        echo $errstr;
202
        echo '
203
            </div>';
204
    } else {
205
        echo '
206
      <div class="card-body px-5">
207
        <div class="card-text my-2">
208
          You have successfully ' .
209
          ($user_code_approved ? 'approved ' : 'denied ') .
210
          'the user code. Please return to your device for further
211
          instructions.
212
        </div> <!-- end row -->
213
      </div> <!-- end card-body-->';
214
    }
215
216
    Content::printCollapseEnd();
217
    Content::printFooter();
218
}
219
220
/**
221
 * verifyUserCodeParam
222
 *
223
 * This function checks for the presence of a 'user_code' query parameter.
224
 * If found, the dbService checkUserCode action is called to get the
225
 * associated client_id. Then the database is queried to find the details of
226
 * that client_id. The results are stored in the clientparams PHP session
227
 * variable. If no user_code was passed in, then the clientparams PHP
228
 * session variable is used. The final check verifies that all required
229
 * client info is available. If all of that is true, then this function
230
 * returns true.
231
 *
232
 * @return bool True if all required client registration info associated
233
 *         with the user_code is available. False otherwise.
234
 */
235
function verifyUserCodeParam()
236
{
237
    $retval = false; // Assume user code & other session info is not valid
238
239
    $log = new Loggit();
240
241
    // If idphint/selected_idp were previously set in the clientparams
242
    // PHP session variable, get them this time around.
243
    $clientparams = array_intersect_key(
244
        json_decode(Util::getSessionVar('clientparams'), true),
245
        ['idphint' => 1, 'selected_idp' => 1]
246
    );
247
248
    // If a user_code was passed in, use that to get the associated
249
    // clientparams. Otherwise, get clientparams from the PHP session.
250
    $user_code = Util::getGetorPostVar('user_code');
251
    if (strlen($user_code) > 0) {
252
        Util::unsetSessionVar('clientparams'); // Don't use any previous values
253
        $log->info('Calling checkUserCode dbService method...');
254
        $dbs = new DBService();
255
        if (
256
            ($dbs->checkUserCode($user_code)) &&
0 ignored issues
show
Bug introduced by
The method checkUserCode() does not seem to exist on object<CILogon\Service\DBService>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
257
            (!($dbs->status & 1))
258
        ) { // STATUS_OK codes are even
259
            if (strlen($dbs->client_id) > 0) {
260
                // Use the client_id associated with the user_code to get
261
                // the rest of the OAuth2 client registration information.
262
                $clientparams['user_code'] = $dbs->user_code;
0 ignored issues
show
Bug introduced by
The property user_code does not seem to exist in CILogon\Service\DBService.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
263
                $clientparams['client_id'] = $dbs->client_id;
0 ignored issues
show
Bug introduced by
The property client_id does not seem to exist in CILogon\Service\DBService.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
264
                $clientparams['scope'] = $dbs->scope;
0 ignored issues
show
Bug introduced by
The property scope does not seem to exist in CILogon\Service\DBService.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
265
                // getOIDCClientParams assumes client_id is stored in the
266
                // passed-in $clientparams variable.
267
                Util::getOIDCClientParams($clientparams);
268
                // If no scope was requested, then assume ALL scopes
269
                // 'scope' is a space-separated string, while 
270
                // client_scopes is a JSON list; need to transform into
271
                // space-separated string.
272
                if (strlen($clientparams['scope']) == 0) {
273
                    $clientparams['scope'] = implode(
274
                        ' ',
275
                        json_decode($clientparams['client_scopes'], true)
276
                    );
277
                }
278
            } else {
279
                Util::setSessionVar('user_code_error_msg', 'Unable to find a client matching the user code.');
280
            }
281
        } else { // STATUS_ERROR code returned
282
            $errstr = 'Error checking user code.'; // Generic error message
283
            if (!is_null($dbs->status)) {
284
                $errstr = array_search($dbs->status, DBService::$STATUS);
285
                // Customize error messages for Device Authz Grant flow
286
                if ($dbs->status == 0x10001) {
287
                    $errstr = 'User code not found.';
288
                } elseif ($db->status == 0x10003) {
0 ignored issues
show
Bug introduced by
The variable $db does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
289
                    $errstr = 'User code expired.';
290
                }
291
            }
292
            Util::setSessionVar('user_code_error_msg', $errstr);
293
        }
294
    } else { // No user_code passed in, so check the PHP session clientparams
295
        $clientparams = json_decode(Util::getSessionVar('clientparams'), true);
296
    }
297
298
    // If no error so far, check all of the client parameters
299
    if (
300
        (strlen(Util::getSessionVar('user_code_error_msg')) == 0) &&
301
        (isset($clientparams['user_code'])) &&
302
        (isset($clientparams['client_id'])) &&
303
        (isset($clientparams['scope'])) &&
304
        (isset($clientparams['client_name'])) &&
305
        (isset($clientparams['client_home_url'])) &&
306
        (isset($clientparams['client_callback_uri'])) &&
307
        (isset($clientparams['client_scopes'])) &&
308
        (isset($clientparams['clientstatus'])) &&
309
        (!($clientparams['clientstatus'] & 1))
310
    ) { // STATUS_OK codes are even
311
        $retval = true;
312
        Util::setSessionVar('clientparams', json_encode($clientparams));
313
    } else {
314
        Util::unsetSessionVar('clientparams');
315
    }
316
317
    // Save idphint/selected_idp from query parameters to PHP session
318
    $idphint = Util::getGetVar('idphint');
319
    $selected_idp = Util::getGetVar('selected_idp');
320
    if (
321
        (strlen($idphint) > 0) ||
322
        (strlen($selected_idp) > 0)
323
    ) {
324
        if (strlen($idphint) > 0) {
325
            $clientparams['idphint'] = $idphint;
326
        }
327
        if (strlen($selected_idp) > 0) {
328
            $clientparams['selected_idp'] = $selected_idp;
329
        }
330
        Util::setSessionVar('clientparams', json_encode($clientparams));
331
    }
332
333
    return $retval;
334
}
335