Files
tinker_tickets/api/revoke_api_key.php
Jared Vititoe ed9c2a39d1 Fix error message disclosure in API endpoints
Replace exception getMessage() exposure with generic error messages
to prevent internal information disclosure. Errors are now logged
with full details while clients receive sanitized responses.

Affected endpoints:
- add_comment, update_comment, delete_comment
- update_ticket, export_tickets
- generate_api_key, revoke_api_key
- manage_templates, manage_workflows, manage_recurring
- custom_fields, get_users

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 18:56:29 -05:00

112 lines
3.0 KiB
PHP

<?php
// API endpoint for revoking API keys (Admin only)
error_reporting(E_ALL);
ini_set('display_errors', 0);
// Apply rate limiting
require_once dirname(__DIR__) . '/middleware/RateLimitMiddleware.php';
RateLimitMiddleware::apply('api');
ob_start();
try {
// Load config
require_once dirname(__DIR__) . '/config/config.php';
require_once dirname(__DIR__) . '/helpers/Database.php';
// Load models
require_once dirname(__DIR__) . '/models/ApiKeyModel.php';
require_once dirname(__DIR__) . '/models/AuditLogModel.php';
// Check authentication via session
session_start();
if (!isset($_SESSION['user']) || !isset($_SESSION['user']['user_id'])) {
throw new Exception("Authentication required");
}
// Check admin privileges
if (!isset($_SESSION['user']['is_admin']) || !$_SESSION['user']['is_admin']) {
throw new Exception("Admin privileges required");
}
// CSRF Protection
require_once dirname(__DIR__) . '/middleware/CsrfMiddleware.php';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$csrfToken = $_SERVER['HTTP_X_CSRF_TOKEN'] ?? '';
if (!CsrfMiddleware::validateToken($csrfToken)) {
http_response_code(403);
throw new Exception("Invalid CSRF token");
}
}
// Only allow POST
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
throw new Exception("Method not allowed");
}
// Get request data
$input = json_decode(file_get_contents('php://input'), true);
if (!$input) {
throw new Exception("Invalid request data");
}
$keyId = (int)($input['key_id'] ?? 0);
if ($keyId <= 0) {
throw new Exception("Valid key ID is required");
}
// Use centralized database connection
$conn = Database::getConnection();
// Get key info for audit log
$apiKeyModel = new ApiKeyModel($conn);
$keyInfo = $apiKeyModel->getKeyById($keyId);
if (!$keyInfo) {
throw new Exception("API key not found");
}
if (!$keyInfo['is_active']) {
throw new Exception("API key is already revoked");
}
// Revoke the key
$success = $apiKeyModel->revokeKey($keyId);
if (!$success) {
throw new Exception("Failed to revoke API key");
}
// Log the action
$auditLog = new AuditLogModel($conn);
$auditLog->log(
$_SESSION['user']['user_id'],
'revoke',
'api_key',
$keyId,
['key_name' => $keyInfo['key_name'], 'key_prefix' => $keyInfo['key_prefix']]
);
// Clear output buffer
ob_end_clean();
// Return success
header('Content-Type: application/json');
echo json_encode([
'success' => true,
'message' => 'API key revoked successfully'
]);
} catch (Exception $e) {
ob_end_clean();
error_log("Revoke API key error: " . $e->getMessage());
header('Content-Type: application/json');
http_response_code(isset($conn) ? 400 : 500);
echo json_encode([
'success' => false,
'error' => 'An internal error occurred'
]);
}