fix: harden auth middleware security #1
4 changed files with 29 additions and 9 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . '/../../helpers.php';
|
require_once __DIR__ . '/../../helpers.php';
|
||||||
require_once __DIR__ . '/_cronUtils.php';
|
require_once __DIR__ . '/_cronUtils.php';
|
||||||
// No runAuth() — this is a cron/public endpoint
|
requireCronSecret();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process all due scheduled tasks.
|
* Process all due scheduled tasks.
|
||||||
|
|
|
||||||
|
|
@ -300,6 +300,30 @@ function sendSMS(string $to, string $body): array {
|
||||||
return ['success' => false, 'message' => $errMsg];
|
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
|
// AUTH MIDDLEWARE
|
||||||
// ============================================
|
// ============================================
|
||||||
|
|
@ -525,18 +549,14 @@ function runAuth(): void {
|
||||||
$businessId = (int) $bizHeader;
|
$businessId = (int) $bizHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if public route
|
// Check if public route (exact match only)
|
||||||
$isPublic = false;
|
$isPublic = false;
|
||||||
foreach (PUBLIC_ROUTES as $route) {
|
foreach (PUBLIC_ROUTES as $route) {
|
||||||
if (str_contains($path, strtolower($route))) {
|
if ($path === strtolower($route)) {
|
||||||
$isPublic = true;
|
$isPublic = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Also allow /api/admin/ paths
|
|
||||||
if (str_contains($path, '/api/admin/')) {
|
|
||||||
$isPublic = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$isPublic) {
|
if (!$isPublic) {
|
||||||
if ($userId <= 0) {
|
if ($userId <= 0) {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . '/../api/helpers.php';
|
require_once __DIR__ . '/../api/helpers.php';
|
||||||
// No runAuth() — cron/public endpoint
|
requireCronSecret();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expire stale chats (older than 20 minutes with no recent activity).
|
* Expire stale chats (older than 20 minutes with no recent activity).
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . '/../api/helpers.php';
|
require_once __DIR__ . '/../api/helpers.php';
|
||||||
require_once __DIR__ . '/../api/config/stripe.php';
|
require_once __DIR__ . '/../api/config/stripe.php';
|
||||||
// No runAuth() — cron/public endpoint
|
requireCronSecret();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scheduled task to handle tab expiry and cleanup.
|
* Scheduled task to handle tab expiry and cleanup.
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue