1440, // match SignonCookieParams lifetime 'path' => '/', 'domain' => '', 'secure' => true, 'httponly' => true, 'samesite' => 'None', ]); session_name('kinsta_pma_sso'); // must match config.inc.php SignonSessionName @session_start(); /* ---------------- Helper: detect AJAX-ish requests ---------------- */ function isAjaxLike(): bool { if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest') { return true; } $accept = $_SERVER['HTTP_ACCEPT'] ?? ''; if (strpos($accept, 'application/json') !== false || strpos($accept, 'text/javascript') !== false) { return true; } if (isset($_GET['route'])) { // e.g. index.php?route=/ background calls return true; } return false; } /* ---------------- Helpers to short-circuit for XHR ---------------- */ function okAjaxNoop(): void { http_response_code(204); // no content, but success header('Cache-Control: no-store, no-cache, must-revalidate'); header('Pragma: no-cache'); exit; } function abortAjaxAuth(string $msg = 'SESSION_EXPIRED'): void { http_response_code(401); header('Cache-Control: no-store, no-cache, must-revalidate'); header('Pragma: no-cache'); header('Content-Type: text/plain; charset=utf-8'); echo $msg; exit; } /* ---------------- Clean fallback login (final compact phpMyAdmin look) ---------------- */ function renderFallbackLogin(bool $fromLogout = false): void { header('Content-Type: text/html; charset=utf-8'); ?> phpMyAdmin

Welcome to phpMyAdmin

Language
Log in
'localhost']; @session_write_close(); header('Location: ./index.php'); exit; } /* ---------------- Logout: show clean form ---------------- */ if (isset($_GET['loggedout'])) { renderFallbackLogin(true); } /* ---------------- Inputs ---------------- */ $token = $_GET['app-key'] ?? $_GET['app-token'] ?? $_GET['token'] ?? null; if ($token !== null) { // cap length $token = substr($token, 0, 256); // allow only safe characters $token = preg_replace('/[^A-Za-z0-9._-]/', '', $token); // if token becomes empty, treat it as missing if ($token === '') { $token = null; } } $haveSSO = !empty($_SESSION['PMA_single_signon_user']) && !empty($_SESSION['PMA_single_signon_password']); if (!$token) { if (isAjaxLike()) { $haveSSO ? okAjaxNoop() : abortAjaxAuth(); } else { if ($haveSSO) { @session_write_close(); header('Location: ./index.php'); exit; } renderFallbackLogin(false); } } /* If SSO already established but a stray token shows up (e.g. copied URL), do not re-validate */ if ($haveSSO) { if (isAjaxLike()) { okAjaxNoop(); } header('Location: ./index.php'); exit; } /* ---------------- Helpers ---------------- */ function parseDbHost(string $raw): array { $host='localhost'; $port='3306'; $socket=null; $s = trim($raw); if ($s === '') return [$host,$port,$socket]; if ($s[0] === '/') return [$host,$port,$s]; if (strpos($s, ':') !== false) { [$h,$rest] = explode(':',$s,2); $host=$h; if ($rest !== '' && $rest[0] === '/') $socket=$rest; elseif (ctype_digit($rest)) $port=$rest; return [$host,$port,$socket]; } return [$s,$port,$socket]; } /** Only use the localhost Nginx+Lua endpoint for env id */ function getEnvIdViaLocalNginx(?array &$dbg = null): ?string { if (!function_exists('curl_init')) { return null; } $tries = [ ['url' => 'https://localhost/kinsta/api/v1/details', 'headers' => [], 'insecure' => true], ['url' => 'http://127.0.0.1/kinsta/api/v1/details', 'headers' => ['Host: localhost'], 'insecure' => false], ]; foreach ($tries as $t) { $ch = curl_init($t['url']); $opts = [ CURLOPT_HTTPHEADER => $t['headers'], CURLOPT_RETURNTRANSFER => true, CURLOPT_CONNECTTIMEOUT => 2, CURLOPT_TIMEOUT => 3, ]; if ($t['insecure']) { $opts[CURLOPT_SSL_VERIFYPEER] = false; $opts[CURLOPT_SSL_VERIFYHOST] = 0; } curl_setopt_array($ch, $opts); $resp = curl_exec($ch); $err = curl_error($ch); $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if (is_array($dbg)) { $dbg[] = [ 'url' => $t['url'], 'code' => $code, 'err' => $err, 'body' => is_string($resp) ? substr($resp, 0, 200) : null, ]; } if ($resp !== false && $code === 200) { $j = json_decode($resp, true); if ( is_array($j) && isset($j['meta_kinsta_env_id']) && is_scalar($j['meta_kinsta_env_id']) ) { $envId = trim((string) $j['meta_kinsta_env_id']); if ($envId !== '') { return $envId; } } } } return null; } /* ---------------- Derive env id ---------------- */ $dbgLua = []; $envId = getEnvIdViaLocalNginx($dbgLua); if (!$envId) { isAjaxLike() ? abortAjaxAuth() : renderFallbackLogin(false); } /* ---------------- Prevent double-validation ---------------- */ if (!isset($_SESSION['PMA_SSO_used_tokens'])) $_SESSION['PMA_SSO_used_tokens'] = []; if (in_array($token, $_SESSION['PMA_SSO_used_tokens'], true)) { // Already validated in this session; don’t try again if (isAjaxLike()) { okAjaxNoop(); } @session_write_close(); header('Location: ./index.php'); exit; } /* ---------------- Validate token ---------------- */ if (!function_exists('curl_init')) { isAjaxLike() ? abortAjaxAuth() : renderFallbackLogin(false); } $GQL_ENDPOINT = getenv('KINSTA_GQL_ENDPOINT') ?: 'https://graphql-router.kinsta.com'; $gql = <<<'GRAPHQL' mutation ValidateAppKey($idEnvironment: String!, $token: String!, $keyType: String) { validateAppKey(idEnvironment: $idEnvironment, token: $token, keyType: $keyType) { id createdAt status } } GRAPHQL; $payload = json_encode(['query'=>$gql,'variables'=>['idEnvironment'=>$envId,'token'=>$token]], JSON_UNESCAPED_SLASHES); $ch = curl_init($GQL_ENDPOINT); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ['Content-Type: application/json'], CURLOPT_POSTFIELDS => $payload, CURLOPT_TIMEOUT => 8, ]); $response = curl_exec($ch); $curlErr = curl_error($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($response === false) { isAjaxLike() ? abortAjaxAuth('NETWORK_ERROR') : renderFallbackLogin(false); } $data = json_decode($response, true); $valid = isset($data['data']['validateAppKey']) && is_array($data['data']['validateAppKey']); if (!$valid) { isAjaxLike() ? abortAjaxAuth('TOKEN_INVALID') : renderFallbackLogin(false); } $_SESSION['PMA_SSO_used_tokens'][] = $token; /* ---------------- Load DB creds from secret ---------------- */ if ( !defined('SERVER_SECRET_DB_USER') || !defined('SERVER_SECRET_DB_PASSWORD') || !defined('SERVER_SECRET_DB_HOST') ) { // If the constants are not available, we can't SSO; fall back to login form / 401. isAjaxLike() ? abortAjaxAuth('NO_DB_CONSTANTS') : renderFallbackLogin(false); } [$dbHost, $dbPort, $dbSocket] = parseDbHost(SERVER_SECRET_DB_HOST); /* ---------------- Set PMA SSO session vars ---------------- */ $_SESSION['PMA_single_signon_user'] = SERVER_SECRET_DB_USER; $_SESSION['PMA_single_signon_password'] = SERVER_SECRET_DB_PASSWORD; if ($dbSocket) { $_SESSION['PMA_single_signon_socket'] = $dbSocket; $_SESSION['PMA_single_signon_host'] = 'localhost'; $_SESSION['PMA_single_signon_port'] = ''; } else { $_SESSION['PMA_single_signon_host'] = $dbHost; $_SESSION['PMA_single_signon_port'] = $dbPort; } if (empty($_SESSION['PMA_single_signon_HMAC_secret'])) { $_SESSION['PMA_single_signon_HMAC_secret'] = hash('sha1', bin2hex(random_bytes(16))); } $_SESSION['PMA_single_signon_cfgupdate'] = ['verbose' => 'localhost']; @session_write_close(); /* ---------------- Hand off to PMA ---------------- */ header('Location: ./index.php'); exit;