← All tutorials

PHP API Security Checklist: Validation, Authentication and SQL Safety

Start protecting a PHP API with validation, authentication, safe SQL and thoughtful error handling.

PHP code editor, shield and secured API connection
Illustration for this tutorial. The examples and requests shown are educational.

A new PHP endpoint often starts with a few lines of code and grows quickly. Before the route handles real account or customer data, it needs basic boundaries: reject unwanted methods, validate each input, authenticate protected requests, use parameterized SQL, and keep internal errors out of public responses.

The checklist below is a starting point rather than a complete security audit. Threats depend on your infrastructure, authentication model and type of data. Treat security controls as layers, not a single helper you paste into a file.

1. Start with HTTPS and a clear request contract

For public APIs, serve the endpoint over HTTPS and redirect insecure requests at your server or load balancer. Decide which HTTP methods and content types are supported. A POST-only JSON endpoint can reject requests that do not follow that contract.

PHP · minimal method and content-type checks
<?php
declare(strict_types=1);
header('Content-Type: application/json; charset=utf-8');

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    header('Allow: POST');
    http_response_code(405);
    echo json_encode(['error' => 'Method not allowed']);
    exit;
}

$contentType = strtolower(trim(explode(';', $_SERVER['CONTENT_TYPE'] ?? '')[0]));
if ($contentType !== 'application/json') {
    http_response_code(415);
    echo json_encode(['error' => 'Send application/json']);
    exit;
}

A content-type check does not make the payload trustworthy. It only tells your API how the client claims to have encoded the body. You still need to parse and validate it.

2. Validate the parsed input, not just the raw request

Put a reasonable body-size limit at your web server, then validate the data type and required fields in PHP. Handle malformed JSON without displaying PHP warnings or stack traces.

PHP · safe JSON parsing
<?php
try {
    $body = json_decode(
        file_get_contents('php://input'),
        true,
        32,
        JSON_THROW_ON_ERROR
    );
} catch (JsonException $e) {
    http_response_code(400);
    echo json_encode(['error' => 'Invalid JSON body']);
    exit;
}

if (!is_array($body) || array_is_list($body)) {
    http_response_code(422);
    echo json_encode(['error' => 'Expected a JSON object']);
    exit;
}

$name = $body['name'] ?? null;
if (!is_string($name) || trim($name) === '' || mb_strlen($name) > 80) {
    http_response_code(422);
    echo json_encode(['error' => 'Name must be 1–80 characters']);
    exit;
}
For PHP versions without the mbstring extension, mb_strlen() is unavailable. Install/enable the extension or use a length rule that matches the character encoding used by your application.

3. Authenticate and authorize separately

Authentication proves who the caller is; authorization decides what that caller can do. Never assume a user may read another user’s record just because the request has a valid token. Check ownership or role permissions at the operation that accesses the data.

For a simple server-to-server endpoint, you might compare an API key against a secret supplied through an environment variable. This is a simplified learning example, not a replacement for a full identity system.

PHP · server-to-server key check
<?php
$expected = getenv('CODEMASTER_API_KEY');
$provided = $_SERVER['HTTP_X_API_KEY'] ?? '';

if (!is_string($expected) || $expected === '' ||
    !is_string($provided) || !hash_equals($expected, $provided)) {
    http_response_code(401);
    echo json_encode(['error' => 'Unauthorized']);
    exit;
}

// Still check what this authenticated caller is allowed to do.

Never ship the secret in public JavaScript or commit it to GitHub. Browser apps normally need a different authentication design. Rotate exposed keys and monitor failed authentication attempts.

Code editor, security shield and protected API response illustration
Good API security combines authentication, validation, parameterized queries and responsible error handling.

4. Use prepared statements for database values

Do not concatenate untrusted values into SQL queries. PHP PDO can bind values safely to placeholders. See our dedicated PDO prepared statements walkthrough for a complete example.

PHP · parameterized SQL
$stmt = $pdo->prepare('SELECT id, name FROM customers WHERE id = :id');
$stmt->bindValue(':id', $customerId, PDO::PARAM_INT);
$stmt->execute();
$customer = $stmt->fetch(PDO::FETCH_ASSOC);

5. Handle errors safely and log useful context

Unexpected server errors should return a stable generic message to callers and produce an appropriate server-side log entry. Avoid returning SQL connection strings, stack traces, passwords or full request headers. Logs themselves must be access-controlled, retained sensibly and protected from sensitive data leakage.

6. Do not confuse CORS with authentication

CORS tells browsers which origins are allowed to read cross-origin responses. It is not an authentication mechanism and does not stop scripts, curl or server-side clients. Set allowed origins narrowly where browser access is required, and avoid treating Access-Control-Allow-Origin: * as a security feature.

7. Deployment checklist

  • Force HTTPS and store credentials outside public source code.
  • Validate method, body size, content type, data type and acceptable field ranges.
  • Authenticate protected endpoints and authorize access to each resource.
  • Use prepared SQL queries and a least-privilege database account.
  • Rate-limit sensitive routes such as login and password-reset endpoints.
  • Use CSRF protection for cookie-authenticated state-changing browser requests.
  • Use logs and monitoring while keeping secrets and personal data out of error responses.
  • Update PHP and dependencies, and test negative cases before deployment.

Frequently asked questions

Is htmlspecialchars() enough to secure an API?

No. It is useful for HTML output encoding in the right context. API security also needs validation, authentication, authorization, parameterized queries and safe server configuration.

Can I store an API key in a .env file?

Yes, if it remains outside the web-accessible document root and is never committed to a public repository. In managed infrastructure, a secrets manager can offer better rotation and access controls.

Editorial note: examples are provided for learning. Test them in your own environment and review security, privacy and compatibility requirements before using them in production.