Completed
Push — master ( 037e93...fab1f0 )
by Terrence
14:46
created

index-functions.php ➔ printMainPage()   C

Complexity

Conditions 11
Paths 3

Size

Total Lines 97

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
nc 3
nop 0
dl 0
loc 97
rs 5.9187
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 prints out the HTML for the main cilogon.org page.
19
 * Explanatory text is shown as well as a button to log in to an IdP
20
 * and get rerouted to the Shibboleth protected getuser script.
21
 */
22
function printLogonPage()
23
{
24
    $log = new Loggit();
25
    $log->info('Welcome page hit.');
26
27
    Util::setSessionVar('stage', 'logon'); // For Show/Hide Help button clicks
28
29
    Content::printHeader(
30
        'Welcome To The CILogon OpenID Connect Authorization Service'
31
    );
32
33
    $clientparams = json_decode(Util::getSessionVar('clientparams'), true);
34
35
    // If the <hideportalinfo> option is set, do not show the portal info
36
    // if the OIDC redirect_uri or client_id is in the portal list.
37
    $showportalinfo = true;
38
    $skin = Util::getSkin();
39
    if (
40
        ((int)$skin->getConfigOption('portallistaction', 'hideportalinfo') == 1) &&
41
        (
42
            ($skin->inPortalList($clientparams['redirect_uri'])) ||
43
            ($skin->inPortalList($clientparams['client_id']))
44
        )
45
    ) {
46
        $showportalinfo = false;
47
    }
48
49
    if ($showportalinfo) {
50
        printOIDCConsent();
51
    }
52
    Content::printWAYF();
53
    Content::printFooter();
54
}
55
56
/**
57
 * printOIDCErrorPage
58
 *
59
 * This function prints out the HTML for the page when the the various
60
 * OIDC parameters sent by the client are missing or bad.
61
 */
62
function printOIDCErrorPage()
63
{
64
    $log = new Loggit();
65
    $log->warn('Missing or invalid OIDC parameters.');
66
67
    Content::printHeader('CILogon Authorization Endpoint');
68
    Content::printCollapseBegin('oidcdefault', 'CILogon OIDC Authorization Endpoint', false);
0 ignored issues
show
Bug introduced by
The method printCollapseBegin() 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...
69
70
    echo '
71
        <div class="card-body px-5">
72
          <div class="card-text my-2">
73
            You have reached the CILogon OAuth2/OpenID Connect (OIDC) 
74
            Authorization Endpoint. This service is for use by OAuth2/OIDC 
75
            Relying Parties (RPs) to authorize users of the CILogon Service. 
76
            End users should not normally see this page.
77
          </div> <!-- end row -->
78
    ';
79
80
    $client_error_msg = Util::getSessionVar('client_error_msg');
81
    Util::unsetSessionVar('client_error_msg');
82
    if (strlen($client_error_msg) > 0) {
83
        echo '<div class="alert alert-danger" role="alert">', $client_error_msg, '</div>';
84
    } else {
85
        echo '
86
          <div class="card-text my-2">
87
            Possible reasons for seeing this page include:
88
          </div> <!-- end row -->
89
          <div class="card-text my-2">
90
            <ul>
91
              <li>You navigated directly to this page.</li>
92
              <li>You clicked your browser\'s "Back" button.</li>
93
              <li>There was a problem with the OpenID Connect client.</li>
94
            </ul>
95
          </div> <!-- end row -->
96
        ';
97
    }
98
99
    echo '
100
          <div class="card-text my-2">
101
            For assistance, please contact us at the email address at the
102
            bottom of the page.
103
          </div>
104
          <div class="card-text my-2">
105
            <strong>Note:</strong> You must enable cookies in your web 
106
            browser to use this site.
107
          </div>
108
        </div> <!-- end card-body -->
109
    ';
110
111
    Content::printCollapseEnd();
0 ignored issues
show
Bug introduced by
The method printCollapseEnd() 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...
112
    Content::printFooter();
113
}
114
115
/**
116
 * printMainPage
117
 *
118
 * This function is poorly named for the OIDC case, but is called by
119
 * gotUserSucces, so the name stays. This function is called once the
120
 * user has successfully logged on at the selected IdP. In the OIDC
121
 * case, the user's UID is then paired with the OIDC 'code' and
122
 * 'authntime' in the datastore so that it can be fetched later when
123
 * the OIDC client wants to get userinfo or a certificate. There
124
 * really isn't anything 'printed' to the user here. Control is
125
 * simply redirected to the OIDC client with appropriate success or
126
 * error response.
127
 */
128
function printMainPage()
129
{
130
    $clientparams = json_decode(Util::getSessionVar('clientparams'), true);
131
    $redirect = 'Location: ' . $clientparams['redirect_url'];
132
133
    $log = new Loggit();
134
    $log->info('Calling setTransactionState dbService method...');
135
136
    $dbs = new DBService();
137
    if (
138
        ($dbs->setTransactionState(
139
            $clientparams['code'],
140
            Util::getSessionVar('user_uid'),
141
            Util::getSessionVar('authntime'),
142
            Util::getLOA(),
0 ignored issues
show
Bug introduced by
The method getLOA() does not seem to exist on object<CILogon\Service\Util>.

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...
143
            Util::getSessionVar('myproxyinfo')
144
        )) && (!($dbs->status & 1))
145
    ) { // STATUS_OK codes are even
146
        // CIL-360 - Check for Response Mode
147
        // http://openid.net/specs/oauth-v2-multiple-response-types-1_0.html#ResponseModes
148
        if (isset($clientparams['response_mode'])) {
149
            $responsemode = $clientparams['response_mode'];
150
            if ($responsemode == 'query') {
151
                // This is the default mode for 'code' response
152
            } elseif ($responsemode == 'fragment') {
153
                // Replace '?' with '#'
154
                $redirect = str_replace('?', '#', $redirect);
155
            } elseif ($responsemode == 'form_post') {
156
                // https://openid.net/specs/oauth-v2-form-post-response-mode-1_0.html
157
                // At this point, $clientparams['redirect_url'] contains
158
                // both the callback uri and all query string parameters
159
                // that should be passed to the callback uri. We need
160
                // to separate the two so we can put the query parameters
161
                // into hidden <input> fields in the output form.
162
                $orig_redirect_uri = $clientparams['redirect_uri'];
163
                $full_redirect_url = $clientparams['redirect_url'];
164
                $queryparams = str_replace(
165
                    $orig_redirect_uri . '?',
166
                    '',
167
                    $full_redirect_url
168
                );
169
                Util::unsetClientSessionVars();
170
                // Util::unsetAllUserSessionVars();
171
                // Get the components of the response (split by '&')
172
                $comps = explode('&', $queryparams);
173
                $outform = '<html>
174
  <head><title>Submit This Form</title></head>
175
  <body onload="javascript:document.forms[0].submit()">
176
    <form method="post" action="' . $orig_redirect_uri . '">
177
    ';
178
                foreach ($comps as $value) {
179
                    $params = explode('=', $value);
180
                    $outform .= '<input type="hidden" name="' . $params[0] .
181
                         '" value="' . html_entity_decode($params[1]) . '"/>';
182
                }
183
                $outform .= '
184
    </form>
185
  </body>
186
</html>';
187
                $log->info(
188
                    'response_mode=form_post; outputting form' . "\n" .
189
                    $outform
190
                );
191
                echo $outform;
192
                exit; // No further processing necessary
193
            }
194
        }
195
        $log->info('setTransactionState succeeded, redirect to ' . $redirect);
196
        // CIL-507 Special log message for XSEDE
197
        $log->info('USAGE email="' . Util::getSessionVar('email') .
198
                   '" client="' . $clientparams['client_name'] . '"');
199
    } else { // dbservice error
200
        $errstr = '';
201
        if (!is_null($dbs->status)) {
202
            $errstr = array_search($dbs->status, DBService::$STATUS);
203
        }
204
        $redirect = 'Location: ' . $clientparams['redirect_uri'] .
205
            (preg_match('/\?/', $clientparams['redirect_uri']) ? '&' : '?') .
206
            'error=server_error&error_description=' .
207
            'Unable%20to%20associate%20user%20UID%20with%20OIDC%20code' .
208
            ((isset($clientparams['state'])) ?
209
                '&state=' . $clientparams['state'] : '');
210
        $log->info("setTransactionState failed $errstr, redirect to $redirect");
211
        Util::sendErrorAlert(
212
            'dbService Error',
213
            'Error calling dbservice action "setTransactionState" in ' .
214
            'OIDC authorization endpoint\'s printMainPage() method. ' .
215
            $errstr . ' Redirected to ' . $redirect
216
        );
217
        Util::unsetUserSessionVars();
218
    }
219
220
    Util::unsetClientSessionVars();
221
    // Util::unsetAllUserSessionVars();
222
    header($redirect);
223
    exit; // No further processing necessary
224
}
225
226
/**
227
 * printOIDCConsent
228
 *
229
 * This function prints out the block showing the scopes requested by the
230
 * OIDC client.
231
 */
232
function printOIDCConsent()
233
{
234
    // Look in the 'scope' OIDC parameter to see which attributes are
235
    // being requested. The values we care about are 'email', 'profile'
236
    // (for first/last name), and 'edu.uiuc.ncsa.myproxy.getcert'
237
    // (which gives a certificate containing first/last name AND email).
238
    // Anything else should just be output as-is.
239
    $clientparams = json_decode(Util::getSessionVar('clientparams'), true);
240
    $scopes = preg_split("/[\s\+]+/", $clientparams['scope']);
241
    $scopes = array_unique($scopes); // Remove any duplicates
242
243
    Content::printCollapseBegin('oidcconsent', 'Consent to Attribute Release', false);
0 ignored issues
show
Bug introduced by
The method printCollapseBegin() 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...
244
245
    $clientparams = json_decode(Util::getSessionVar('clientparams'), true);
246
    echo '
247
        <div class="card-body px-5">
248
          <div class="card-text my-2">
249
            <a target="_blank" href="' ,
250
            htmlspecialchars($clientparams['client_home_url']) , '">',
251
            htmlspecialchars($clientparams['client_name']) , '</a>' ,
252
            ' requests access to the following information.
253
            If you do not approve this request, do not proceed.
254
          </div> <!-- end row -->
255
          <ul>
256
    ';
257
258
    if (in_array('openid', $scopes)) {
259
        echo '<li>Your CILogon user identifier</li>';
260
        $scopes = array_diff($scopes, ['openid']);
261
    }
262
    if (
263
        (in_array('profile', $scopes)) ||
264
        (in_array('edu.uiuc.ncsa.myproxy.getcert', $scopes))
265
    ) {
266
        echo '<li>Your name</li>';
267
        $scopes = array_diff($scopes, ['profile']);
268
    }
269
    if (
270
        (in_array('email', $scopes)) ||
271
        (in_array('edu.uiuc.ncsa.myproxy.getcert', $scopes))
272
    ) {
273
        echo '<li>Your email address</li>';
274
        $scopes = array_diff($scopes, ['email']);
275
    }
276
    if (in_array('org.cilogon.userinfo', $scopes)) {
277
        echo '<li>Your username and affiliation from your identity provider</li>';
278
        $scopes = array_diff($scopes, ['org.cilogon.userinfo']);
279
    }
280
    if (in_array('edu.uiuc.ncsa.myproxy.getcert', $scopes)) {
281
        echo '<li>A certificate that allows "' ,
282
        htmlspecialchars($clientparams['client_name']) ,
283
        '" to act on your behalf</li>';
284
        $scopes = array_diff($scopes, ['edu.uiuc.ncsa.myproxy.getcert']);
285
    }
286
    // Output any remaining scopes as-is
287
    foreach ($scopes as $value) {
288
        echo '<li>', $value , '</li>';
289
    }
290
    echo '</ul>
291
        </div> <!-- end card-body -->
292
    ';
293
294
    Content::printCollapseEnd();
0 ignored issues
show
Bug introduced by
The method printCollapseEnd() 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...
295
}
296
297
/**
298
 * verifyOIDCParams
299
 *
300
 * This function verifies that all of the various OIDC parameters are
301
 * set in the PHP session. First, the function checks if an OIDC
302
 * client has passed appropriate parameters to the authorization
303
 * endpoint. If so, we call the 'real' OA4MP OIDC authorization
304
 * endpoint and let it verify the client parameters. Upon successful
305
 * return, we call the getClient() function of the dbService to get
306
 * the OIDC client name and homepage for display to the user. All
307
 * client parameters (including the ones passed in) are saved to the
308
 * 'clientparams' PHP session variable, which is encoded as a JSON
309
 * token to preserve arrays. If there are any errors, false is returned
310
 * and an email is sent. In some cases the session variable
311
 * 'client_error_msg' is set so it can be displayed by the
312
 * printOIDCErrorPage() function.
313
 *
314
 * @return bool True if the various parameters related to the OIDC
315
 *         session are present. False otherwise.
316
 */
317
function verifyOIDCParams()
318
{
319
    $retval = false; // Assume OIDC session info is not valid
320
321
    // Combine the $_GET and $_POST arrays into a single array which can be
322
    // stored in the 'clientparams' session variable as a JSON object.
323
    $clientparams = array();
324
    foreach ($_GET as $key => $value) {
325
        $clientparams[$key] = $value;
326
    }
327
    foreach ($_POST as $key => $value) {
328
        $clientparams[$key] = $value;
329
    }
330
331
    // If the 'redirect_uri' parameter was passed in then let the 'real'
332
    // OA4MP OIDC authz endpoint handle parse the request since it might be
333
    // possible to return an error code to the client.
334
    if (isset($clientparams['redirect_uri'])) {
335
        $ch = curl_init();
336
        if ($ch !== false) {
337
            $url = OAUTH2_CREATE_TRANSACTION_URL;
338
            if (count($_GET) > 0) {
339
                // CIL-658 Look for double-encoded spaces in 'scope'
340
                foreach ($_GET as $key => $value) {
341
                    if ($key == 'scope') {
342
                        $_GET[$key] = preg_replace('/\+/', ' ', $value);
343
                        break;
344
                    }
345
                }
346
                $url .= (preg_match('/\?/', $url) ? '&' : '?') .
347
                    http_build_query($_GET);
348
            }
349
            if (count($_POST) > 0) {
350
                curl_setopt($ch, CURLOPT_POST, true);
351
                curl_setopt($ch, CUROPT_POSTFIELDS, http_build_query($_POST));
352
            }
353
            curl_setopt($ch, CURLOPT_URL, $url);
354
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
355
            curl_setopt($ch, CURLOPT_TIMEOUT, 30);
356
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false); // Catch redirects
357
            $output = curl_exec($ch);
358
            if (curl_errno($ch)) { // Send alert on curl errors
359
                Util::sendErrorAlert(
360
                    'cUrl Error',
361
                    'cUrl Error    = ' . curl_error($ch) . "\n" .
362
                    "URL Accessed  = $url" .
363
                    "\n\n" .
364
                    'clientparams = ' . print_r($clientparams, true)
365
                );
366
                $clientparams = array();
367
            } else {
368
                $info = curl_getinfo($ch);
369
                if ($info !== false) {
370
                    if (
371
                        (isset($info['http_code'])) &&
372
                        ($info['http_code'] == 200)
373
                    ) {
374
                        // The OA4MP OIDC authz endpoint responded with 200
375
                        // (success). The body of the message should be a
376
                        // JSON token containing the appropriate parameters
377
                        // such as the 'code'.
378
                        $json = json_decode($output, true);
379
                        if (isset($json['code'])) {
380
                            // Got 'code' - save to session and call
381
                            // dbService 'getClient' to get info about
382
                            // OIDC client to display to user
383
                            $clientparams['redirect_url'] =
384
                                $clientparams['redirect_uri'] .
385
                                (preg_match('/\?/', $clientparams['redirect_uri']) ? '&' : '?') .
386
                                http_build_query($json);
387
                            $clientparams['code'] = $json['code'];
388
                            // CIL-618 Read OIDC client info from database
389
                            if (!Util::getOIDCClientParams($clientparams)) {
0 ignored issues
show
Bug introduced by
The method getOIDCClientParams() does not seem to exist on object<CILogon\Service\Util>.

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...
390
                                Util::sendErrorAlert(
391
                                    'getOIDCClientParams Error',
392
                                    'Error getting OIDC client parameters ' .
393
                                    'in verifyOIDCParams() function for ' .
394
                                    'client_id="' .
395
                                    $clientparams['client_id'] . '".'
396
                                );
397
                                $clientparams = array();
398
                            }
399
                        } else {
400
                            // Either the output returned was not a valid
401
                            // JSON token, or there was no 'code' found in
402
                            // the returned JSON token.
403
                            // CIL-575 Check for a "status=..." line in the
404
                            // returned $output to print a useful error
405
                            // message to the user (and in the error email).
406
                            $errortxt = '';
407
                            if (
408
                                preg_match(
409
                                    '/status=(\d+)/',
410
                                    $output,
411
                                    $matches
412
                                )
413
                            ) {
414
                                $errornum = $matches[1];
415
                                $errstr = array_search(
416
                                    $errornum,
417
                                    DBService::$STATUS
418
                                );
419
                                $errortxt = @DBService::$STATUS_TEXT[$errstr];
420
                            }
421
422
                            Util::sendErrorAlert(
423
                                'OA4MP OIDC authz endpoint error',
424
                                (!empty($errortxt) ? $errortxt :
425
                                'The OA4MP OIDC authorization endpoint ' .
426
                                'returned an HTTP response 200, but either ' .
427
                                'the output was not a valid JSON token, or ' .
428
                                'there was no "code" in the JSON token. ' .
429
                                ((strlen($output) > 0) ?
430
                                    "\n\nReturned output =\n$output" : '')) .
431
                                "\n\n" .
432
                                'curl_getinfo = ' . print_r($info, true) . "\n\n" .
433
                                'clientparams = ' . print_r($clientparams, true) .
434
                                "\n"
435
                            );
436
                            Util::setSessionVar(
437
                                'client_error_msg',
438
                                'There was an unrecoverable error during the transaction. ' .
439
                                'CILogon system administrators have been notified. ' .
440
                                (!empty($errortxt) ? "<p><b>Error message: $errortxt</b><p>" : '')
441
                            );
442
                            $clientparams = array();
443
                        }
444
                    } elseif (
445
                        (isset($info['http_code'])) &&
446
                        ($info['http_code'] == 302)
447
                    ) {
448
                        // The OA4MP OIDC authz endpoint responded with 302
449
                        // (redirect) which indicates an OIDC error was
450
                        // detected. We need to check the response for an
451
                        // 'error' and simply redirect error to OIDC client.
452
                        $redirect_url = '';
453
                        if (isset($info['redirect_url'])) {
454
                            $redirect_url = $info['redirect_url'];
455
                            $clientparams['redirect_url'] = $redirect_url;
456
                            // CIL-407 - In case of two question marks '?'
457
                            // in redirect_url (caused by OIDC authz endpoint
458
                            // blindly appending "?error=..."), change all
459
                            // but the first '?' to '&'.
460
                            // https://stackoverflow.com/a/37150213
461
                            if (substr_count($redirect_url, '?') > 1) {
462
                                $arr = explode('?', $redirect_url, 2);
463
                                $arr[1] = str_replace('?', '&', $arr[1]);
464
                                $redirect_url = implode('?', $arr);
465
                            }
466
                        }
467
                        // Get components of redirect_url - need 'query'
468
                        $comps = parse_url($redirect_url);
469
                        if ($comps !== false) {
470
                            // Look for 'error' in query
471
                            $query = '';
472
                            if (isset($comps['query'])) {
473
                                $query = $comps['query'];
474
                                $query = html_entity_decode($query);
475
                            }
476
                            $queries = explode('&', $query);
477
                            $params = array();
478
                            foreach ($queries as $value) {
479
                                $x = explode('=', $value);
480
                                $params[$x[0]] = $x[1];
481
                            }
482
                            if (isset($params['error'])) {
483
                                // Got 'error' - simply return to OIDC client
484
                                Util::unsetAllUserSessionVars();
485
                                header("Location: $redirect_url");
486
                                exit; // No further processing necessary
487
                            } else { // Weird params - Should never get here!
488
                                Util::sendErrorAlert(
489
                                    'OA4MP OIDC 302 Error',
490
                                    'The OA4MP OIDC authz endpoint ' .
491
                                    'returned a 302 redirect (error) ' .
492
                                    'response, but there was no "error" ' .
493
                                    "query parameter.\n\n" .
494
                                    "redirect_url = $redirect_url\n\n" .
495
                                    'clientparams = ' .
496
                                    print_r($clientparams, true) .
497
                                    "\n"
498
                                );
499
                                $clientparams = array();
500
                            }
501
                        } else { // parse_url($redirect_url) gave error
502
                            Util::sendErrorAlert(
503
                                'parse_url(redirect_url) error',
504
                                'There was an error when attempting to ' .
505
                                'parse the redirect_url. This should never ' .
506
                                "happen.\n\n" .
507
                                "redirect_url = $redirect_url\n\n" .
508
                                'clientparams = ' . print_r($clientparams, true) .
509
                                "\n"
510
                            );
511
                            $clientparams = array();
512
                        }
513
                    } else {
514
                        // An HTTP return code other than 200 (success) or
515
                        // 302 (redirect) means that the OA4MP OIDC authz
516
                        // endpoint tried to handle an unrecoverable error,
517
                        // possibly by outputting HTML. If so, then we
518
                        // ignore it and output our own error message to the
519
                        // user.
520
                        Util::sendErrorAlert(
521
                            'OA4MP OIDC authz endpoint error',
522
                            'The OA4MP OIDC authorization endpoint returned ' .
523
                            'an HTTP response other than 200 or 302. ' .
524
                            ((strlen($output) > 0) ?
525
                                "\n\nReturned output =\n$output" : '') .
526
                            "\n\n" .
527
                            'curl_getinfo = ' . print_r($info, true) . "\n\n" .
528
                            'clientparams = ' . print_r($clientparams, true) .
529
                            "\n"
530
                        );
531
                        // CIL-423 Better end-user error output for errors.
532
                        // Scan output for ServletException message.
533
                        $errstr = '';
534
                        if (
535
                            preg_match(
536
                                '/javax.servlet.ServletException:\s?(.*)/',
537
                                $output,
538
                                $matches
539
                            )
540
                        ) {
541
                            $output = '';
542
                            $errstr = '
543
                            <div>
544
                            <p>Error Message: <b>' .
545
                            $matches[1] . '</b>.</p>
546
                            <ul>
547
                            <li>Did you <b>register</b> your OAuth2/OIDC client? If not, go
548
                            <b><a target="_blank" href="https://' .
549
                            Util::getHN()
550
                            . '/oauth2/register">here</a></b> to do so.</li>
551
                            <li>Did you receive confirmation that your OAuth2/OIDC client
552
                            was <b>approved</b>? If not, please wait up to 48 hours for an
553
                            approval email from CILogon administrators.</li>
554
                            <li>Did you configure your OAuth2/OIDC client with the
555
                            registered <b>client ID and secret</b>?</li>
556
                            </ul>
557
                            </div>';
558
                        }
559
                        Util::setSessionVar(
560
                            'client_error_msg',
561
                            'There was an unrecoverable error during the transaction. ' .
562
                            'CILogon system administrators have been notified.' .
563
                            ((strlen($errstr) > 0) ? $errstr : '') .
564
                            ((strlen($output) > 0) ?
565
                            '<br/><pre>' .
566
                            preg_replace('/\+/', ' ', $output) .
567
                            '</pre>' : '')
568
                        );
569
                        $clientparams = array();
570
                    }
571
                } else { // curl_getinfo() returned false - should not happen
572
                    Util::sendErrorAlert(
573
                        'curl_getinfo error',
574
                        'When attempting to talk to the OA4MP OIDC ' .
575
                        'authorization endpoint, curl_getinfo() returned ' .
576
                        "false. This should never happen.\n\n" .
577
                        'clientparams = ' . print_r($clientparams, true) . "\n"
578
                    );
579
                    $clientparams = array();
580
                }
581
            }
582
            curl_close($ch);
583
        } else { // curl_init() returned false - should not happen
584
            Util::sendErrorAlert(
585
                'curl_init error',
586
                'When attempting to talk to the OA4MP OIDC authorization ' .
587
                'endpoint, curl_init() returned false. This should never ' .
588
                "happen.\n\n" .
589
                'clientparams = ' . print_r($clientparams, true) . "\n"
590
            );
591
            $clientparams = array();
592
        }
593
594
    // If redirect_uri was not passed in, but one of the other required OIDC
595
    // parameters WAS passed in, then assume that this was an attempt by an
596
    // OIDC client to use the authz endpoint, and display an error message
597
    // that at least one parameter (redirect_uri) was missing from the
598
    // request. Note that since we don't have a redirect_uri, we cannot
599
    // return code flow back to the OIDC client.
600
    } elseif (
601
        (isset($clientparams['scope'])) ||
602
        (isset($clientparams['response_type'])) ||
603
        (isset($clientparams['client_id']))
604
    ) {
605
        Util::sendErrorAlert(
606
            'CILogon OIDC authz endpoint error',
607
            'The CILogon OIDC authorization endpoint received a request ' .
608
            'from an OIDC client, but at least one of the required ' .
609
            'parameters (redirect_uri) was missing. ' .
610
            "\n\n" .
611
            'clientparams = ' . print_r($clientparams, true) .
612
            "\n"
613
        );
614
        Util::setSessionVar(
615
            'client_error_msg',
616
            'It appears that an OpenID Connect client attempted to ' .
617
            'initiate a session with the CILogon Service, but at least ' .
618
            'one of the requried parameters was missing. CILogon ' .
619
            'system administrators have been notified.'
620
        );
621
        $clientparams = array();
622
623
    // If none of the required OIDC authz endpoint parameters were passed
624
    // in, then this might be a later step in the authz process. So check
625
    // the session variable array 'clientparams' for the required
626
    // information.
627
    } else {
628
        $clientparams = json_decode(Util::getSessionVar('clientparams'), true);
629
    }
630
631
    // Now check to verify all variables have data
632
    if (
633
        (isset($clientparams['redirect_uri'])) &&
634
        (isset($clientparams['scope'])) &&
635
        (isset($clientparams['response_type'])) &&
636
        (isset($clientparams['client_id'])) &&
637
        (isset($clientparams['code'])) &&
638
        (isset($clientparams['client_name'])) &&
639
        (isset($clientparams['client_home_url'])) &&
640
        (isset($clientparams['client_callback_uri'])) &&
641
        (isset($clientparams['redirect_url'])) &&
642
        (isset($clientparams['clientstatus'])) &&
643
        (!($clientparams['clientstatus'] & 1))
644
    ) { // STATUS_OK* are even
645
        $retval = true;
646
        Util::setSessionVar('clientparams', json_encode($clientparams));
647
    }
648
649
    return $retval;
650
}
651