fix: harden auth middleware security #1

Merged
schwifty merged 1 commit from schwifty/fix-auth-security into main 2026-03-23 01:44:02 +00:00
4 changed files with 29 additions and 9 deletions

View file

@ -1,7 +1,7 @@
<?php
require_once __DIR__ . '/../../helpers.php';
require_once __DIR__ . '/_cronUtils.php';
// No runAuth() — this is a cron/public endpoint
requireCronSecret();
/**
* Process all due scheduled tasks.

View file

@ -300,6 +300,30 @@ function sendSMS(string $to, string $body): array {
return ['success' => false, 'message' => $errMsg];
}
// ============================================
// CRON AUTH
// ============================================
/**
* Require a valid X-Cron-Secret header for cron/scheduled task endpoints.
* The secret is read from the PAYFRIT_CRON_SECRET environment variable.
* Aborts with 403 if missing or mismatched.
*/
function requireCronSecret(): void {
$expected = trim(getenv('PAYFRIT_CRON_SECRET') ?: '');
if ($expected === '') {
error_log('[cron_auth] PAYFRIT_CRON_SECRET env var is not set. Blocking request.');
http_response_code(403);
jsonResponse(['OK' => false, 'ERROR' => 'cron_secret_not_configured'], 403);
}
$provided = headerValue('X-Cron-Secret');
if ($provided === '' || !hash_equals($expected, $provided)) {
http_response_code(403);
jsonResponse(['OK' => false, 'ERROR' => 'invalid_cron_secret'], 403);
}
}
// ============================================
// AUTH MIDDLEWARE
// ============================================
@ -525,18 +549,14 @@ function runAuth(): void {
$businessId = (int) $bizHeader;
}
// Check if public route
// Check if public route (exact match only)
$isPublic = false;
foreach (PUBLIC_ROUTES as $route) {
if (str_contains($path, strtolower($route))) {
if ($path === strtolower($route)) {
$isPublic = true;
break;
}
}
// Also allow /api/admin/ paths
if (str_contains($path, '/api/admin/')) {
$isPublic = true;
}
if (!$isPublic) {
if ($userId <= 0) {

View file

@ -1,6 +1,6 @@
<?php
require_once __DIR__ . '/../api/helpers.php';
// No runAuth() — cron/public endpoint
requireCronSecret();
/**
* Expire stale chats (older than 20 minutes with no recent activity).

View file

@ -1,7 +1,7 @@
<?php
require_once __DIR__ . '/../api/helpers.php';
require_once __DIR__ . '/../api/config/stripe.php';
// No runAuth() — cron/public endpoint
requireCronSecret();
/**
* Scheduled task to handle tab expiry and cleanup.