$v) { if (preg_match('/^(REDIRECT_)+' . preg_quote($base, '/') . '$/', $k)) { return $v; } } return ''; }; // QMUL releases group membership in the "groups" attribute (semicolon- // separated plain tokens, e.g. GG-ORG-IT_Services). config.json's // sessionGroupName must match ("groups"). if (empty($_SERVER['groups'])) { $_SERVER['groups'] = $unwind('groups'); } // Is there a live Shibboleth session? With lazy sessions (requireSession 0) // this is empty for an anonymous visitor and populated once they've been // through SSO. Check the canonical session id in every REDIRECT_ / dash / // underscore form mod_shib and mod_rewrite might expose. $loggedIn = false; foreach ($_SERVER as $k => $v) { if (!empty($v) && preg_match('/^(REDIRECT_)*Shib[_-]Session[_-]ID$/i', $k)) { $loggedIn = true; break; } } if (!$loggedIn && (!empty($_SERVER['REMOTE_USER']) || !empty($_SERVER['groups']))) { $loggedIn = true; } // "valid-user" pseudo-group: any authenticated user, regardless of groups // (same convention as profile.php). The library matches the media item's // groups against the user's groups claim, so give every logged-in user a // synthetic "valid-user" membership and let the normal check pass. if ($loggedIn) { $userGroups = array_filter(array_map('trim', explode(';', (string) $_SERVER['groups']))); if (!in_array('valid-user', array_map('strtolower', $userGroups), true)) { $userGroups[] = 'valid-user'; $_SERVER['groups'] = implode(';', $userGroups); } } if (!empty($t4_config['config'])) { AccessControl\Core\Config::setJSON($_SERVER['DOCUMENT_ROOT'].$t4_config['config']); } $accessControl = \AccessControl\Core\TypeFactory::getInstance(); $accessControl->isRestrictedMedia($t4_config['restrict'], $t4_config['logic']); } catch (Exception $e) { if ($e->getCode() === 1001) { // File not found. header('Location: '.\AccessControl\Core\Config::get('redirectNotFound')); die(); } elseif ($e->getCode() === 1000) { // Access denied. Split the two cases: // - not logged in -> send to SSO login, then back to the file // - logged in but wrong group -> genuine 403 if (empty($loggedIn)) { // Not authenticated -> initiate Shibboleth SSO and return to this // exact file afterwards. The SP session initiator expects // ?target= (not the library's ?r=). Behind CloudFront/ // ALB, SSL is terminated upstream, so trust X-Forwarded-Proto and // default to https. $scheme = !empty($_SERVER['HTTP_X_FORWARDED_PROTO']) ? $_SERVER['HTTP_X_FORWARDED_PROTO'] : ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'https'); $target = $scheme . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; // loginUrl in config.json is the SP session initiator (/Shibboleth.sso/Login). $loginUrl = \AccessControl\Core\Config::get('loginUrl'); header('Location: ' . $loginUrl . '?target=' . urlencode($target)); die(); } header('Location: '.\AccessControl\Core\Config::get('redirectNoAccess')); die(); } else { http_response_code(503); die(); } } ?>