cilogon /
service
This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 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 | Content::printHeader( |
||
| 28 | 'Welcome To The CILogon OpenID Connect Authorization Service' |
||
| 29 | ); |
||
| 30 | |||
| 31 | $clientparams = json_decode(Util::getSessionVar('clientparams'), true); |
||
| 32 | |||
| 33 | // If the <hideportalinfo> option is set, do not show the portal info |
||
| 34 | // if the OIDC redirect_uri or client_id is in the portal list. |
||
| 35 | $showportalinfo = true; |
||
| 36 | $skin = Util::getSkin(); |
||
| 37 | if ( |
||
| 38 | ((int)$skin->getConfigOption('portallistaction', 'hideportalinfo') == 1) && |
||
| 39 | ( |
||
| 40 | ($skin->inPortalList($clientparams['redirect_uri'])) || |
||
| 41 | ($skin->inPortalList($clientparams['client_id'])) |
||
| 42 | ) |
||
| 43 | ) { |
||
| 44 | $showportalinfo = false; |
||
| 45 | } |
||
| 46 | |||
| 47 | if ($showportalinfo) { |
||
| 48 | Content::printOIDCConsent(); |
||
|
0 ignored issues
–
show
|
|||
| 49 | } |
||
| 50 | Content::printWAYF(); |
||
| 51 | Content::printFooter(); |
||
| 52 | } |
||
| 53 | |||
| 54 | /** |
||
| 55 | * printOIDCErrorPage |
||
| 56 | * |
||
| 57 | * This function prints out the HTML for the page when the the various |
||
| 58 | * OIDC parameters sent by the client are missing or bad. |
||
| 59 | */ |
||
| 60 | function printOIDCErrorPage() |
||
| 61 | { |
||
| 62 | $log = new Loggit(); |
||
| 63 | $log->warn('Missing or invalid OIDC parameters.'); |
||
| 64 | |||
| 65 | Content::printHeader('CILogon Authorization Endpoint'); |
||
| 66 | Content::printCollapseBegin('oidcdefault', 'CILogon OIDC Authorization Endpoint', false); |
||
| 67 | |||
| 68 | echo ' |
||
| 69 | <div class="card-body px-5"> |
||
| 70 | <div class="card-text my-2"> |
||
| 71 | You have reached the CILogon OAuth2/OpenID Connect (OIDC) |
||
| 72 | Authorization Endpoint. This service is for use by OAuth2/OIDC |
||
| 73 | Relying Parties (RPs) to authorize users of the CILogon Service. |
||
| 74 | End users should not normally see this page. |
||
| 75 | </div> <!-- end row --> |
||
| 76 | '; |
||
| 77 | |||
| 78 | $client_error_msg = Util::getSessionVar('client_error_msg'); |
||
| 79 | Util::unsetSessionVar('client_error_msg'); |
||
| 80 | if (strlen($client_error_msg) > 0) { |
||
| 81 | echo '<div class="alert alert-danger" role="alert">', $client_error_msg, '</div>'; |
||
| 82 | } else { |
||
| 83 | echo ' |
||
| 84 | <div class="card-text my-2"> |
||
| 85 | Possible reasons for seeing this page include: |
||
| 86 | </div> <!-- end row --> |
||
| 87 | <div class="card-text my-2"> |
||
| 88 | <ul> |
||
| 89 | <li>You navigated directly to this page.</li> |
||
| 90 | <li>You clicked your browser\'s "Back" button.</li> |
||
| 91 | <li>There was a problem with the OpenID Connect client.</li> |
||
| 92 | </ul> |
||
| 93 | </div> <!-- end row --> |
||
| 94 | '; |
||
| 95 | } |
||
| 96 | |||
| 97 | echo ' |
||
| 98 | <div class="card-text my-2"> |
||
| 99 | For assistance, please contact us at the email address at the |
||
| 100 | bottom of the page. |
||
| 101 | </div> |
||
| 102 | <div class="card-text my-2"> |
||
| 103 | <strong>Note:</strong> You must enable cookies in your web |
||
| 104 | browser to use this site. |
||
| 105 | </div> |
||
| 106 | </div> <!-- end card-body --> |
||
| 107 | '; |
||
| 108 | |||
| 109 | Content::printCollapseEnd(); |
||
| 110 | Content::printFooter(); |
||
| 111 | } |
||
| 112 | |||
| 113 | /** |
||
| 114 | * printMainPage |
||
| 115 | * |
||
| 116 | * This function is poorly named for the OIDC case, but is called by |
||
| 117 | * gotUserSuccess, so the name stays. This function is called once the |
||
| 118 | * user has successfully logged on at the selected IdP. In the OIDC |
||
| 119 | * case, the user's UID is then paired with the OIDC 'code' and |
||
| 120 | * 'authntime' in the datastore so that it can be fetched later when |
||
| 121 | * the OIDC client wants to get userinfo or a certificate. There |
||
| 122 | * really isn't anything 'printed' to the user here. Control is |
||
| 123 | * simply redirected to the OIDC client with appropriate success or |
||
| 124 | * error response. |
||
| 125 | */ |
||
| 126 | function printMainPage() |
||
| 127 | { |
||
| 128 | $clientparams = json_decode(Util::getSessionVar('clientparams'), true); |
||
| 129 | $redirect = 'Location: ' . $clientparams['redirect_url']; |
||
| 130 | |||
| 131 | $log = new Loggit(); |
||
| 132 | $log->info('Calling setTransactionState dbService method...'); |
||
| 133 | |||
| 134 | $dbs = new DBService(); |
||
| 135 | if ( |
||
| 136 | ($dbs->setTransactionState( |
||
| 137 | $clientparams['code'], |
||
| 138 | Util::getSessionVar('user_uid'), |
||
| 139 | Util::getSessionVar('authntime'), |
||
| 140 | Util::getLOA(), |
||
| 141 | Util::getSessionVar('myproxyinfo') |
||
| 142 | )) && (!($dbs->status & 1)) |
||
| 143 | ) { // STATUS_OK codes are even |
||
| 144 | // CIL-360 - Check for Response Mode |
||
| 145 | // http://openid.net/specs/oauth-v2-multiple-response-types-1_0.html#ResponseModes |
||
| 146 | if (isset($clientparams['response_mode'])) { |
||
| 147 | $responsemode = $clientparams['response_mode']; |
||
| 148 | if ($responsemode == 'query') { |
||
| 149 | // This is the default mode for 'code' response |
||
| 150 | } elseif ($responsemode == 'fragment') { |
||
| 151 | // Replace '?' with '#' |
||
| 152 | $redirect = str_replace('?', '#', $redirect); |
||
| 153 | } elseif ($responsemode == 'form_post') { |
||
| 154 | // https://openid.net/specs/oauth-v2-form-post-response-mode-1_0.html |
||
| 155 | // At this point, $clientparams['redirect_url'] contains |
||
| 156 | // both the callback uri and all query string parameters |
||
| 157 | // that should be passed to the callback uri. We need |
||
| 158 | // to separate the two so we can put the query parameters |
||
| 159 | // into hidden <input> fields in the output form. |
||
| 160 | $orig_redirect_uri = $clientparams['redirect_uri']; |
||
| 161 | $full_redirect_url = $clientparams['redirect_url']; |
||
| 162 | $queryparams = str_replace( |
||
| 163 | $orig_redirect_uri . '?', |
||
| 164 | '', |
||
| 165 | $full_redirect_url |
||
| 166 | ); |
||
| 167 | Util::unsetClientSessionVars(); |
||
| 168 | // Util::unsetAllUserSessionVars(); |
||
| 169 | // Get the components of the response (split by '&') |
||
| 170 | $comps = explode('&', $queryparams); |
||
| 171 | $outform = '<html> |
||
| 172 | <head><title>Submit This Form</title></head> |
||
| 173 | <body onload="javascript:document.forms[0].submit()"> |
||
| 174 | <form method="post" action="' . $orig_redirect_uri . '"> |
||
| 175 | '; |
||
| 176 | foreach ($comps as $value) { |
||
| 177 | $params = explode('=', $value); |
||
| 178 | $outform .= '<input type="hidden" name="' . $params[0] . |
||
| 179 | '" value="' . html_entity_decode($params[1]) . '"/>'; |
||
| 180 | } |
||
| 181 | $outform .= ' |
||
| 182 | </form> |
||
| 183 | </body> |
||
| 184 | </html>'; |
||
| 185 | $log->info( |
||
| 186 | 'response_mode=form_post; outputting form' . "\n" . |
||
| 187 | $outform |
||
| 188 | ); |
||
| 189 | echo $outform; |
||
| 190 | exit; // No further processing necessary |
||
| 191 | } |
||
| 192 | } |
||
| 193 | $log->info('setTransactionState succeeded, redirect to ' . $redirect); |
||
| 194 | // CIL-507 Special log message for XSEDE |
||
| 195 | $email = Util::getSessionVar('email'); |
||
| 196 | $clientname = $clientparams['client_name']; |
||
| 197 | $log->info("USAGE email=\"$email\" client=\"$clientname\""); |
||
| 198 | Util::logXSEDEUsage($clientname, $email); |
||
|
0 ignored issues
–
show
The method
logXSEDEUsage() 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...
|
|||
| 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 | * verifyOIDCParams |
||
| 228 | * |
||
| 229 | * This function verifies that all of the various OIDC parameters are |
||
| 230 | * set in the PHP session. First, the function checks if an OIDC |
||
| 231 | * client has passed appropriate parameters to the authorization |
||
| 232 | * endpoint. If so, we call the 'real' OA4MP OIDC authorization |
||
| 233 | * endpoint and let it verify the client parameters. Upon successful |
||
| 234 | * return, we read the database to get the OIDC client information |
||
| 235 | * to display to the user. All client parameters (including the ones |
||
| 236 | * passed in) are saved to the 'clientparams' PHP session variable, |
||
| 237 | * which is encoded as a JSON token to preserve arrays. If there are |
||
| 238 | * any errors, false is returned and an email is sent. In some cases |
||
| 239 | * the session variable 'client_error_msg' is set so it can be |
||
| 240 | * displayed by the printOIDCErrorPage() function. |
||
| 241 | * |
||
| 242 | * @return bool True if the various parameters related to the OIDC |
||
| 243 | * session are present. False otherwise. |
||
| 244 | */ |
||
| 245 | function verifyOIDCParams() |
||
| 246 | { |
||
| 247 | $retval = false; // Assume OIDC session info is not valid |
||
| 248 | |||
| 249 | // Combine the $_GET and $_POST arrays into a single array which can be |
||
| 250 | // stored in the 'clientparams' session variable as a JSON object. |
||
| 251 | $clientparams = array(); |
||
| 252 | foreach ($_GET as $key => $value) { |
||
| 253 | $clientparams[$key] = $value; |
||
| 254 | } |
||
| 255 | foreach ($_POST as $key => $value) { |
||
| 256 | $clientparams[$key] = $value; |
||
| 257 | } |
||
| 258 | |||
| 259 | // CIL-624 If X509 certs are disabled, check for 'getcert' scope. |
||
| 260 | // If found, show an error message. |
||
| 261 | $scope = Util::getGetVar('scope'); |
||
| 262 | if ( |
||
| 263 | (defined('DISABLE_X509')) && |
||
| 264 | (DISABLE_X509 === true) && |
||
| 265 | (preg_match('/edu.uiuc.ncsa.myproxy.getcert/', $scope)) |
||
| 266 | ) { |
||
| 267 | Util::sendErrorAlert( |
||
| 268 | 'CILogon OIDC authz endpoint error', |
||
| 269 | 'The CILogon OIDC authorization endpoint received a request ' . |
||
| 270 | 'including the "edu.ncsa.uiuc.myproxy.getcert" scope, ' . |
||
| 271 | 'but the server is configured with DISABLE_X509 to prevent ' . |
||
| 272 | 'downloading certificates. ' . |
||
| 273 | "\n\n" . |
||
| 274 | 'clientparams = ' . print_r($clientparams, true) . |
||
| 275 | "\n" |
||
| 276 | ); |
||
| 277 | Util::setSessionVar( |
||
| 278 | 'client_error_msg', |
||
| 279 | 'The CILogon Service is currently configured to prevent ' . |
||
| 280 | 'downloading X.509 certificates, but the incoming request ' . |
||
| 281 | 'included the "edu.ncsa.uiuc.myproxy.getcert" scope. ' . |
||
| 282 | 'CILogon system administrators have been notified.' |
||
| 283 | ); |
||
| 284 | $clientparams = array(); |
||
| 285 | |||
| 286 | // If the 'redirect_uri' parameter was passed in then let the 'real' |
||
| 287 | // OA4MP OIDC authz endpoint handle parse the request since it might be |
||
| 288 | // possible to return an error code to the client. |
||
| 289 | } elseif (isset($clientparams['redirect_uri'])) { |
||
| 290 | $ch = curl_init(); |
||
| 291 | if ($ch !== false) { |
||
| 292 | $url = OAUTH2_CREATE_TRANSACTION_URL; |
||
| 293 | if (count($_GET) > 0) { |
||
| 294 | // CIL-658 Look for double-encoded spaces in 'scope' |
||
| 295 | if (strlen($scope) > 0) { |
||
| 296 | $_GET['scope'] = preg_replace('/(\+|%2B)/', ' ', $scope); |
||
| 297 | } |
||
| 298 | $url .= (preg_match('/\?/', $url) ? '&' : '?') . |
||
| 299 | http_build_query($_GET); |
||
| 300 | } |
||
| 301 | if (count($_POST) > 0) { |
||
| 302 | curl_setopt($ch, CURLOPT_POST, true); |
||
| 303 | curl_setopt($ch, CUROPT_POSTFIELDS, http_build_query($_POST)); |
||
| 304 | } |
||
| 305 | curl_setopt($ch, CURLOPT_URL, $url); |
||
| 306 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); |
||
| 307 | curl_setopt($ch, CURLOPT_TIMEOUT, 30); |
||
| 308 | curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false); // Catch redirects |
||
| 309 | $output = curl_exec($ch); |
||
| 310 | if (curl_errno($ch)) { // Send alert on curl errors |
||
| 311 | Util::sendErrorAlert( |
||
| 312 | 'cUrl Error', |
||
| 313 | 'cUrl Error = ' . curl_error($ch) . "\n" . |
||
| 314 | "URL Accessed = $url" . |
||
| 315 | "\n\n" . |
||
| 316 | 'clientparams = ' . print_r($clientparams, true) |
||
| 317 | ); |
||
| 318 | $clientparams = array(); |
||
| 319 | } else { |
||
| 320 | $info = curl_getinfo($ch); |
||
| 321 | if ($info !== false) { |
||
| 322 | if ( |
||
| 323 | (isset($info['http_code'])) && |
||
| 324 | ($info['http_code'] == 200) |
||
| 325 | ) { |
||
| 326 | // The OA4MP OIDC authz endpoint responded with 200 |
||
| 327 | // (success). The body of the message should be a |
||
| 328 | // JSON token containing the appropriate parameters |
||
| 329 | // such as the 'code'. |
||
| 330 | $json = json_decode($output, true); |
||
| 331 | if (isset($json['code'])) { |
||
| 332 | // Got 'code' - save to session and read OIDC |
||
| 333 | // client info from the database to display |
||
| 334 | // to the user |
||
| 335 | $clientparams['redirect_url'] = |
||
| 336 | $clientparams['redirect_uri'] . |
||
| 337 | (preg_match('/\?/', $clientparams['redirect_uri']) ? '&' : '?') . |
||
| 338 | http_build_query($json); |
||
| 339 | $clientparams['code'] = $json['code']; |
||
| 340 | // CIL-618 Read OIDC client info from database |
||
| 341 | if (!Util::getOIDCClientParams($clientparams)) { |
||
| 342 | Util::sendErrorAlert( |
||
| 343 | 'getOIDCClientParams Error', |
||
| 344 | 'Error getting OIDC client parameters ' . |
||
| 345 | 'in verifyOIDCParams() function for ' . |
||
| 346 | 'client_id="' . |
||
| 347 | $clientparams['client_id'] . '".' |
||
| 348 | ); |
||
| 349 | $clientparams = array(); |
||
| 350 | } |
||
| 351 | } else { |
||
| 352 | // Either the output returned was not a valid |
||
| 353 | // JSON token, or there was no 'code' found in |
||
| 354 | // the returned JSON token. |
||
| 355 | $errortxt = getErrorStatusText($output, $clientparams); |
||
| 356 | |||
| 357 | Util::sendErrorAlert( |
||
| 358 | 'OA4MP OIDC authz endpoint error', |
||
| 359 | (!empty($errortxt) ? $errortxt : |
||
| 360 | 'The OA4MP OIDC authorization endpoint ' . |
||
| 361 | 'returned an HTTP response 200, but either ' . |
||
| 362 | 'the output was not a valid JSON token, or ' . |
||
| 363 | 'there was no "code" in the JSON token. ' . |
||
| 364 | ((strlen($output) > 0) ? |
||
| 365 | "\n\nReturned output =\n$output" : '')) . |
||
| 366 | "\n\n" . |
||
| 367 | 'curl_getinfo = ' . print_r($info, true) . "\n\n" . |
||
| 368 | 'clientparams = ' . print_r($clientparams, true) . |
||
| 369 | "\n" |
||
| 370 | ); |
||
| 371 | Util::setSessionVar( |
||
| 372 | 'client_error_msg', |
||
| 373 | 'There was an unrecoverable error during the transaction. ' . |
||
| 374 | 'CILogon system administrators have been notified. ' . |
||
| 375 | (!empty($errortxt) ? "<p><b>Error message: $errortxt</b><p>" : '') |
||
| 376 | ); |
||
| 377 | $clientparams = array(); |
||
| 378 | } |
||
| 379 | } elseif ( |
||
| 380 | (isset($info['http_code'])) && |
||
| 381 | ($info['http_code'] == 302) |
||
| 382 | ) { |
||
| 383 | // The OA4MP OIDC authz endpoint responded with 302 |
||
| 384 | // (redirect) which indicates an OIDC error was |
||
| 385 | // detected. We need to check the response for an |
||
| 386 | // 'error' and simply redirect error to OIDC client. |
||
| 387 | $redirect_url = ''; |
||
| 388 | if (isset($info['redirect_url'])) { |
||
| 389 | $redirect_url = $info['redirect_url']; |
||
| 390 | $clientparams['redirect_url'] = $redirect_url; |
||
| 391 | // CIL-407 - In case of two question marks '?' |
||
| 392 | // in redirect_url (caused by OIDC authz endpoint |
||
| 393 | // blindly appending "?error=..."), change all |
||
| 394 | // but the first '?' to '&'. |
||
| 395 | // https://stackoverflow.com/a/37150213 |
||
| 396 | if (substr_count($redirect_url, '?') > 1) { |
||
| 397 | $arr = explode('?', $redirect_url, 2); |
||
| 398 | $arr[1] = str_replace('?', '&', $arr[1]); |
||
| 399 | $redirect_url = implode('?', $arr); |
||
| 400 | } |
||
| 401 | } |
||
| 402 | // Get components of redirect_url - need 'query' |
||
| 403 | $comps = parse_url($redirect_url); |
||
| 404 | if ($comps !== false) { |
||
| 405 | // Look for 'error' in query |
||
| 406 | $query = ''; |
||
| 407 | if (isset($comps['query'])) { |
||
| 408 | $query = $comps['query']; |
||
| 409 | $query = html_entity_decode($query); |
||
| 410 | } |
||
| 411 | $queries = explode('&', $query); |
||
| 412 | $params = array(); |
||
| 413 | foreach ($queries as $value) { |
||
| 414 | $x = explode('=', $value); |
||
| 415 | $params[$x[0]] = $x[1]; |
||
| 416 | } |
||
| 417 | if (isset($params['error'])) { |
||
| 418 | // Got 'error' - simply return to OIDC client |
||
| 419 | Util::unsetAllUserSessionVars(); |
||
| 420 | header("Location: $redirect_url"); |
||
| 421 | exit; // No further processing necessary |
||
| 422 | } else { // Weird params - Should never get here! |
||
| 423 | Util::sendErrorAlert( |
||
| 424 | 'OA4MP OIDC 302 Error', |
||
| 425 | 'The OA4MP OIDC authz endpoint ' . |
||
| 426 | 'returned a 302 redirect (error) ' . |
||
| 427 | 'response, but there was no "error" ' . |
||
| 428 | "query parameter.\n\n" . |
||
| 429 | "redirect_url = $redirect_url\n\n" . |
||
| 430 | 'clientparams = ' . |
||
| 431 | print_r($clientparams, true) . |
||
| 432 | "\n" |
||
| 433 | ); |
||
| 434 | $clientparams = array(); |
||
| 435 | } |
||
| 436 | } else { // parse_url($redirect_url) gave error |
||
| 437 | Util::sendErrorAlert( |
||
| 438 | 'parse_url(redirect_url) error', |
||
| 439 | 'There was an error when attempting to ' . |
||
| 440 | 'parse the redirect_url. This should never ' . |
||
| 441 | "happen.\n\n" . |
||
| 442 | "redirect_url = $redirect_url\n\n" . |
||
| 443 | 'clientparams = ' . print_r($clientparams, true) . |
||
| 444 | "\n" |
||
| 445 | ); |
||
| 446 | $clientparams = array(); |
||
| 447 | } |
||
| 448 | } else { |
||
| 449 | // An HTTP return code other than 200 (success) or |
||
| 450 | // 302 (redirect) means that the OA4MP OIDC authz |
||
| 451 | // endpoint tried to handle an unrecoverable error, |
||
| 452 | // possibly by outputting HTML. If so, then we |
||
| 453 | // ignore it and output our own error message to the |
||
| 454 | // user. |
||
| 455 | Util::sendErrorAlert( |
||
| 456 | 'OA4MP OIDC authz endpoint error', |
||
| 457 | 'The OA4MP OIDC authorization endpoint returned ' . |
||
| 458 | 'an HTTP response other than 200 or 302. ' . |
||
| 459 | ((strlen($output) > 0) ? |
||
| 460 | "\n\nReturned output =\n$output" : '') . |
||
| 461 | "\n\n" . |
||
| 462 | 'curl_getinfo = ' . print_r($info, true) . "\n\n" . |
||
| 463 | 'clientparams = ' . print_r($clientparams, true) . |
||
| 464 | "\n" |
||
| 465 | ); |
||
| 466 | // CIL-423 Better end-user error output for errors. |
||
| 467 | // Scan output for ServletException message. |
||
| 468 | $errstr = ''; |
||
| 469 | if ( |
||
| 470 | preg_match( |
||
| 471 | '/javax.servlet.ServletException:\s?(.*)/', |
||
| 472 | $output, |
||
| 473 | $matches |
||
| 474 | ) |
||
| 475 | ) { |
||
| 476 | $output = ''; |
||
| 477 | $errstr = ' |
||
| 478 | <div> |
||
| 479 | <p>Error Message: <b>' . |
||
| 480 | $matches[1] . '</b>.</p> |
||
| 481 | <ul> |
||
| 482 | <li>Did you <b>register</b> your OAuth2/OIDC client? If not, go |
||
| 483 | <b><a target="_blank" href="https://' . |
||
| 484 | Util::getHN() |
||
| 485 | . '/oauth2/register">here</a></b> to do so.</li> |
||
| 486 | <li>Did you receive confirmation that your OAuth2/OIDC client |
||
| 487 | was <b>approved</b>? If not, please wait up to 48 hours for an |
||
| 488 | approval email from CILogon administrators.</li> |
||
| 489 | <li>Did you configure your OAuth2/OIDC client with the |
||
| 490 | registered <b>client ID and secret</b>?</li> |
||
| 491 | </ul> |
||
| 492 | </div>'; |
||
| 493 | } |
||
| 494 | Util::setSessionVar( |
||
| 495 | 'client_error_msg', |
||
| 496 | 'There was an unrecoverable error during the transaction. ' . |
||
| 497 | 'CILogon system administrators have been notified.' . |
||
| 498 | ((strlen($errstr) > 0) ? $errstr : '') . |
||
| 499 | ((strlen($output) > 0) ? |
||
| 500 | '<br/><pre>' . |
||
| 501 | preg_replace('/\+/', ' ', $output) . |
||
| 502 | '</pre>' : '') |
||
| 503 | ); |
||
| 504 | $clientparams = array(); |
||
| 505 | } |
||
| 506 | } else { // curl_getinfo() returned false - should not happen |
||
| 507 | Util::sendErrorAlert( |
||
| 508 | 'curl_getinfo error', |
||
| 509 | 'When attempting to talk to the OA4MP OIDC ' . |
||
| 510 | 'authorization endpoint, curl_getinfo() returned ' . |
||
| 511 | "false. This should never happen.\n\n" . |
||
| 512 | 'clientparams = ' . print_r($clientparams, true) . "\n" |
||
| 513 | ); |
||
| 514 | $clientparams = array(); |
||
| 515 | } |
||
| 516 | } |
||
| 517 | curl_close($ch); |
||
| 518 | } else { // curl_init() returned false - should not happen |
||
| 519 | Util::sendErrorAlert( |
||
| 520 | 'curl_init error', |
||
| 521 | 'When attempting to talk to the OA4MP OIDC authorization ' . |
||
| 522 | 'endpoint, curl_init() returned false. This should never ' . |
||
| 523 | "happen.\n\n" . |
||
| 524 | 'clientparams = ' . print_r($clientparams, true) . "\n" |
||
| 525 | ); |
||
| 526 | $clientparams = array(); |
||
| 527 | } |
||
| 528 | |||
| 529 | // If redirect_uri was not passed in, but one of the other required OIDC |
||
| 530 | // parameters WAS passed in, then assume that this was an attempt by an |
||
| 531 | // OIDC client to use the authz endpoint, and display an error message |
||
| 532 | // that at least one parameter (redirect_uri) was missing from the |
||
| 533 | // request. Note that since we don't have a redirect_uri, we cannot |
||
| 534 | // return code flow back to the OIDC client. |
||
| 535 | } elseif ( |
||
| 536 | (isset($clientparams['client_id'])) || |
||
| 537 | (isset($clientparams['scope'])) || |
||
| 538 | (isset($clientparams['response_type'])) |
||
| 539 | ) { |
||
| 540 | $missing = 'redirect_uri' . |
||
| 541 | ((isset($clientparams['client_id'])) ? '' : ', client_id') . |
||
| 542 | ((isset($clientparams['scope'])) ? '' : ', scope') . |
||
| 543 | ((isset($clientparams['response_type'])) ? '' : ', response_type'); |
||
| 544 | Util::sendErrorAlert( |
||
| 545 | 'CILogon OIDC authz endpoint error', |
||
| 546 | 'The CILogon OIDC authorization endpoint received a request ' . |
||
| 547 | 'from an OIDC client, but at least one of the required ' . |
||
| 548 | 'parameters (' . $missing . ') was missing. ' . |
||
| 549 | "\n\n" . |
||
| 550 | 'clientparams = ' . print_r($clientparams, true) . |
||
| 551 | "\n" |
||
| 552 | ); |
||
| 553 | Util::setSessionVar( |
||
| 554 | 'client_error_msg', |
||
| 555 | 'It appears that an OpenID Connect client attempted to ' . |
||
| 556 | 'initiate a session with the CILogon Service, but at least ' . |
||
| 557 | 'one of the requried parameters (' . $missing . ') ' . |
||
| 558 | 'was missing. CILogon system administrators have been notified.' |
||
| 559 | ); |
||
| 560 | $clientparams = array(); |
||
| 561 | |||
| 562 | // If none of the required OIDC authz endpoint parameters were passed |
||
| 563 | // in, then this might be a later step in the authz process. So check |
||
| 564 | // the session variable array 'clientparams' for the required |
||
| 565 | // information. |
||
| 566 | } else { |
||
| 567 | $clientparams = json_decode(Util::getSessionVar('clientparams'), true); |
||
| 568 | } |
||
| 569 | |||
| 570 | // Now check to verify all variables have data |
||
| 571 | if ( |
||
| 572 | (isset($clientparams['redirect_uri'])) && |
||
| 573 | (isset($clientparams['scope'])) && |
||
| 574 | (isset($clientparams['response_type'])) && |
||
| 575 | (isset($clientparams['client_id'])) && |
||
| 576 | (isset($clientparams['code'])) && |
||
| 577 | (isset($clientparams['client_name'])) && |
||
| 578 | (isset($clientparams['client_home_url'])) && |
||
| 579 | (isset($clientparams['client_callback_uri'])) && |
||
| 580 | (isset($clientparams['client_scopes'])) && |
||
| 581 | (isset($clientparams['redirect_url'])) && |
||
| 582 | (isset($clientparams['clientstatus'])) && |
||
| 583 | (!($clientparams['clientstatus'] & 1)) |
||
| 584 | ) { // STATUS_OK* are even |
||
| 585 | $retval = true; |
||
| 586 | Util::setSessionVar('clientparams', json_encode($clientparams)); |
||
| 587 | } |
||
| 588 | |||
| 589 | return $retval; |
||
| 590 | } |
||
| 591 | |||
| 592 | /** |
||
| 593 | * getErrorStatusText |
||
| 594 | * |
||
| 595 | * This function is called when the OA4MP OIDC authz endpoint responds with |
||
| 596 | * a 200 (success), but the returned output was not a valid JSON token, or |
||
| 597 | * there was no 'code' found in the returned JSON token. So attempt to scan |
||
| 598 | * the returned $output for error messages that can be returned to the end |
||
| 599 | * user and added to the alert email sent to admins. |
||
| 600 | * |
||
| 601 | * @param string $output The returned text from the OA4MP authz endpoint. |
||
| 602 | * @param array $clientparams An array of the incoming OIDC client parameters. |
||
| 603 | * @return string Error text to be displayed to the end user and added to |
||
| 604 | * the alert email sent to admins. |
||
| 605 | */ |
||
| 606 | function getErrorStatusText($output, $clientparams) |
||
| 607 | { |
||
| 608 | $errstr = ''; |
||
| 609 | $errtxt = ''; |
||
| 610 | |||
| 611 | // CIL-575 Check the $output for a "status=..." line and convert |
||
| 612 | // the error number to an error message defined in CILogon\Service\Util. |
||
| 613 | if (preg_match('/status=(\d+)/', $output, $matches)) { |
||
| 614 | $errnum = $matches[1]; |
||
| 615 | $errstr = array_search($errnum, DBService::$STATUS); |
||
| 616 | $errtxt = @DBService::$STATUS_TEXT[$errstr]; |
||
| 617 | } |
||
| 618 | |||
| 619 | // CIL-831 The OA4MP code returns a STATUS_INTERNAL_ERROR when there is |
||
| 620 | // weirdness in the incoming client parameters. Look for some special |
||
| 621 | // error conditions and set the error text appropriately. |
||
| 622 | if ( |
||
| 623 | (strlen($errstr) == 0) || |
||
| 624 | ($errstr == 'STATUS_INTERNAL_ERROR') || |
||
| 625 | ($errstr == 'STATUS_CREATE_TRANSACTION_FAILED') || |
||
| 626 | ($errstr == 'STATUS_MISSING_PARAMETER_ERROR') |
||
| 627 | ) { |
||
| 628 | $params = [ |
||
| 629 | 'redirect_uri', |
||
| 630 | 'scope', |
||
| 631 | 'response_type', |
||
| 632 | 'client_id', |
||
| 633 | 'prompt', |
||
| 634 | 'response_mode', |
||
| 635 | ]; |
||
| 636 | foreach ($params as $value) { |
||
| 637 | $$value = @$clientparams[$value]; |
||
| 638 | } |
||
| 639 | |||
| 640 | if (empty($scope)) { |
||
|
0 ignored issues
–
show
The variable
$scope seems to never exist, and therefore empty should always return true. Did you maybe rename this variable?
This check looks for calls to This is most likely caused by the renaming of a variable or the removal of a function/method parameter. Loading history...
|
|||
| 641 | $errtxt = "Missing or empty scope parameter."; |
||
| 642 | } elseif (empty($client_id)) { |
||
|
0 ignored issues
–
show
The variable
$client_id seems to never exist, and therefore empty should always return true. Did you maybe rename this variable?
This check looks for calls to This is most likely caused by the renaming of a variable or the removal of a function/method parameter. Loading history...
|
|||
| 643 | $errtxt = "Missing or empty client_id parameter."; |
||
| 644 | } elseif (empty($response_type)) { |
||
|
0 ignored issues
–
show
The variable
$response_type seems to never exist, and therefore empty should always return true. Did you maybe rename this variable?
This check looks for calls to This is most likely caused by the renaming of a variable or the removal of a function/method parameter. Loading history...
|
|||
| 645 | $errtxt = "Missing or empty response_type parameter."; |
||
| 646 | } elseif (preg_match('/[\+%"\']/', $scope)) { |
||
| 647 | $errtxt = "Invalid characters found in scope parameter, may be URL encoded twice."; |
||
| 648 | } elseif (preg_match('/[A-Z]/', $scope)) { |
||
| 649 | $errtxt = "Upper case characters found in scope parameter."; |
||
| 650 | } elseif ($response_type != 'code') { |
||
| 651 | $errtxt = "Unsupported response_type parameter. Only code is supported."; |
||
| 652 | } elseif ((!empty($prompt)) && ($prompt != 'login') && ($prompt != 'select_account')) { |
||
|
0 ignored issues
–
show
The variable
$prompt seems to never exist, and therefore empty should always return true. Did you maybe rename this variable?
This check looks for calls to This is most likely caused by the renaming of a variable or the removal of a function/method parameter. Loading history...
|
|||
| 653 | $errtxt = "Unsupported prompt parameter. Only login and select_account are supported."; |
||
| 654 | } elseif ( |
||
| 655 | (!empty($response_mode)) && |
||
|
0 ignored issues
–
show
The variable
$response_mode seems to never exist, and therefore empty should always return true. Did you maybe rename this variable?
This check looks for calls to This is most likely caused by the renaming of a variable or the removal of a function/method parameter. Loading history...
|
|||
| 656 | ($response_mode != 'query') && |
||
| 657 | ($response_mode != 'fragment') && |
||
| 658 | ($response_mode != 'form_post') |
||
| 659 | ) { |
||
| 660 | $errtxt = "Unsupported response_mode parameter."; |
||
| 661 | } |
||
| 662 | |||
| 663 | // CIL-697 The OA4MP code should eventually return an |
||
| 664 | // "error_description=..." field that can give detailed error text to |
||
| 665 | // replace the default text associated with STATUS_INTERNAL_ERROR. |
||
| 666 | // CIL-909 Use the error_description field only if $errtxt is still |
||
| 667 | // empty, OR if the $errstr was STATUS_CREATE_TRANSACTION_FAILED |
||
| 668 | // (i.e., "Failed to initialize OIDC flow."). |
||
| 669 | if ( |
||
| 670 | ((strlen($errtxt) == 0) || |
||
| 671 | ($errstr == 'STATUS_CREATE_TRANSACTION_FAILED')) && |
||
| 672 | (preg_match('/error_description=([^\r\n]+)/', $output, $matches)) |
||
| 673 | ) { |
||
| 674 | $errtxt = urldecode($matches[1]); |
||
| 675 | } |
||
| 676 | } |
||
| 677 | |||
| 678 | return $errtxt; |
||
| 679 | } |
||
| 680 |
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.