'invalid_token', 'error_description' => $message], JSON_UNESCAPED_SLASHES); exit(); } $authorization = $_SERVER['HTTP_AUTHORIZATION'] ?? ''; if ($authorization === '' && function_exists('apache_request_headers')) { $headers = apache_request_headers(); if (isset($headers['Authorization'])) { $authorization = $headers['Authorization']; } } if (stripos($authorization, 'bearer ') !== 0) { unauthorized('Bearer token required.'); } $token = trim(substr($authorization, 7)); if ($token === '') { unauthorized('Bearer token required.'); } $oauthService = new OAuthService($pdo); $tokenRecord = $oauthService->getAccessToken($token); if (!$tokenRecord) { unauthorized('Access token is invalid or expired.'); } $oauthService->recordTokenUsage($tokenRecord['token_hash']); $personId = (int) $tokenRecord['person_id']; $sql = "SELECT p.pkisp_id AS person_id, p.isp_firstname_en, p.isp_lastname_en, p.isp_email, u.isu_name, u.isu_status FROM ist_tbl_people p JOIN ist_tbl_users u ON u.fkisp_id_of = p.pkisp_id WHERE p.pkisp_id = :person_id LIMIT 1"; $stmt = $pdo->prepare($sql); $stmt->execute([':person_id' => $personId]); $user = $stmt->fetch(PDO::FETCH_ASSOC); if (!$user) { unauthorized('Associated user account not found.'); } $hubUsername = dsp_resolve_jupyterhub_username( $personId, $user['isu_name'] ?? null, $user['isp_email'] ?? null ); $response = [ 'sub' => (string) $personId, 'person_id' => $personId, 'hub_username' => $hubUsername, 'username' => $user['isu_name'] ?? null, 'email' => $user['isp_email'] ?? null, 'first_name' => $user['isp_firstname_en'] ?? null, 'last_name' => $user['isp_lastname_en'] ?? null, 'role' => $user['isu_status'] ?? null, ]; if (!empty($tokenRecord['scope'])) { $response['scope'] = $tokenRecord['scope']; } echo json_encode($response, JSON_UNESCAPED_SLASHES);