Require auth session for media proxy
This commit is contained in:
@@ -110,7 +110,7 @@ ProxyPassReverse /listen/8000/ http://127.0.0.1:8000/
|
||||
|
||||
`deploy/php/media_proxy.php` is copied into your publish directory by `deploy_client.sh`.
|
||||
|
||||
When `server/.env` contains `CHGRID_HOST_ORIGIN`, `deploy_client.sh` also generates `media_proxy.config.php` in the publish directory so the proxy can enforce the same origin without extra Apache-specific config.
|
||||
When `server/.env` contains `CHGRID_HOST_ORIGIN`, `deploy_client.sh` also generates `media_proxy.config.php` in the publish directory so the proxy can enforce the same origin and validate authenticated sessions without extra Apache-specific config. The generated file derives the local auth-check URL from `server/config.toml`, so custom signaling ports continue to work.
|
||||
|
||||
If you deploy the PHP proxy some other way, you can still provide `CHGRID_HOST_ORIGIN` directly through your PHP/web-server environment.
|
||||
|
||||
|
||||
@@ -165,6 +165,73 @@ function load_proxy_host_origin()
|
||||
return normalize_origin($config['host_origin']);
|
||||
}
|
||||
|
||||
function load_proxy_session_check_url()
|
||||
{
|
||||
$fromEnv = trim((string) getenv('CHGRID_MEDIA_PROXY_SESSION_CHECK_URL'));
|
||||
if ($fromEnv !== '') {
|
||||
return $fromEnv;
|
||||
}
|
||||
|
||||
$configPath = __DIR__ . '/media_proxy.config.php';
|
||||
if (!is_file($configPath)) {
|
||||
return 'http://127.0.0.1:8765/auth/session/check';
|
||||
}
|
||||
$config = require $configPath;
|
||||
if (!is_array($config) || !isset($config['session_check_url'])) {
|
||||
return 'http://127.0.0.1:8765/auth/session/check';
|
||||
}
|
||||
$value = trim((string) $config['session_check_url']);
|
||||
if ($value === '') {
|
||||
return 'http://127.0.0.1:8765/auth/session/check';
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
function require_valid_proxy_session($sessionCheckUrl)
|
||||
{
|
||||
$cookieHeader = isset($_SERVER['HTTP_COOKIE']) ? trim((string) $_SERVER['HTTP_COOKIE']) : '';
|
||||
if ($cookieHeader === '') {
|
||||
send_text(401, 'session required');
|
||||
}
|
||||
if (!function_exists('curl_init')) {
|
||||
send_text(500, 'curl extension is required');
|
||||
}
|
||||
|
||||
$ch = curl_init();
|
||||
if (!$ch) {
|
||||
send_text(500, 'proxy init failed');
|
||||
}
|
||||
|
||||
curl_setopt($ch, CURLOPT_URL, $sessionCheckUrl);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
|
||||
curl_setopt($ch, CURLOPT_MAXREDIRS, 0);
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_NOSIGNAL, true);
|
||||
curl_setopt($ch, CURLOPT_USERAGENT, 'ChatGridMediaProxy/1.0');
|
||||
curl_setopt(
|
||||
$ch,
|
||||
CURLOPT_HTTPHEADER,
|
||||
array(
|
||||
'Cookie: ' . $cookieHeader,
|
||||
'X-Chgrid-Auth-Client: 1',
|
||||
)
|
||||
);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
if ($response === false) {
|
||||
$error = curl_error($ch);
|
||||
curl_close($ch);
|
||||
send_text(502, 'session check failed: ' . $error);
|
||||
}
|
||||
$status = (int) curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
|
||||
curl_close($ch);
|
||||
if ($status !== 204) {
|
||||
send_text(401, 'session required');
|
||||
}
|
||||
}
|
||||
|
||||
function host_matches_suffix($host, $suffix)
|
||||
{
|
||||
if ($suffix === '') {
|
||||
@@ -431,6 +498,7 @@ function resolve_safe_redirect_chain($initialUrl, $allowlistSuffixes, $requestHe
|
||||
$allowlistEnv = getenv('CHGRID_MEDIA_PROXY_ALLOWLIST');
|
||||
$allowlistSuffixes = parse_allowlist_suffixes($allowlistEnv);
|
||||
$allowedOrigin = load_proxy_host_origin();
|
||||
$sessionCheckUrl = load_proxy_session_check_url();
|
||||
if ($allowedOrigin === '') {
|
||||
send_text(500, 'CHGRID_HOST_ORIGIN is required');
|
||||
}
|
||||
@@ -453,6 +521,8 @@ if ($method !== 'GET' && $method !== 'HEAD') {
|
||||
send_text(405, 'method not allowed');
|
||||
}
|
||||
|
||||
require_valid_proxy_session($sessionCheckUrl);
|
||||
|
||||
$rawUrl = isset($_GET['url']) ? trim((string) $_GET['url']) : '';
|
||||
if ($rawUrl === '') {
|
||||
send_text(400, 'missing url query param');
|
||||
|
||||
@@ -39,12 +39,42 @@ if [[ -f "$SERVER_ENV_FILE" ]]; then
|
||||
fi
|
||||
|
||||
if [[ -n "${CHGRID_HOST_ORIGIN:-}" ]]; then
|
||||
session_check_url="$(
|
||||
python3 - "$REPO_ROOT/server/config.toml" <<'PY'
|
||||
from pathlib import Path
|
||||
import sys
|
||||
import tomllib
|
||||
|
||||
config_path = Path(sys.argv[1])
|
||||
host = "127.0.0.1"
|
||||
port = 8765
|
||||
if config_path.exists():
|
||||
with config_path.open("rb") as fp:
|
||||
data = tomllib.load(fp)
|
||||
server = data.get("server", {})
|
||||
bind_ip = str(server.get("bind_ip", host)).strip() or host
|
||||
if bind_ip in {"0.0.0.0", ""}:
|
||||
host = "127.0.0.1"
|
||||
elif bind_ip == "::":
|
||||
host = "[::1]"
|
||||
else:
|
||||
host = bind_ip
|
||||
try:
|
||||
port = int(server.get("port", port))
|
||||
except (TypeError, ValueError):
|
||||
port = 8765
|
||||
print(f"http://{host}:{port}/auth/session/check")
|
||||
PY
|
||||
)"
|
||||
escaped_host_origin=${CHGRID_HOST_ORIGIN//\\/\\\\}
|
||||
escaped_host_origin=${escaped_host_origin//\'/\\\'}
|
||||
escaped_session_check_url=${session_check_url//\\/\\\\}
|
||||
escaped_session_check_url=${escaped_session_check_url//\'/\\\'}
|
||||
cat > "$PUBLISH_DIR/media_proxy.config.php" <<EOF
|
||||
<?php
|
||||
return array(
|
||||
'host_origin' => '$escaped_host_origin',
|
||||
'session_check_url' => '$escaped_session_check_url',
|
||||
);
|
||||
EOF
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user