http clients and apis

API Authentication Patterns

API authentication proves who or what is calling an API. The right pattern depends on the type of client, how secrets are stored, whether users are involved, whether access needs scopes, and how credentials can be revoked.

Authentication answers "who is calling?" Authorisation answers "what may they do?" A real API usually needs both.

API keys

API keys are simple shared secrets. They are common for server-to-server integrations and internal tools.

PHP example
<?php

declare(strict_types=1);

function apiKeyFromHeaders(array $headers): ?string
{
    return isset($headers['X-API-Key']) ? trim((string) $headers['X-API-Key']) : null;
}

var_dump(apiKeyFromHeaders(['X-API-Key' => 'key_123']));
var_dump(apiKeyFromHeaders([]));

// Prints:
// string(7) "key_123"
// NULL

API keys are easy to use but easy to leak. Store only hashed keys where possible, show the full key only once when created, support rotation, and never put keys in URLs.

Bearer tokens

Bearer tokens are sent in the Authorization header. They are common with OAuth and JWT-based APIs.

PHP example
<?php

declare(strict_types=1);

function bearerToken(?string $authorization): ?string
{
    if ($authorization === null) {
        return null;
    }

    if (!preg_match('/^Bearer\s+(.+)$/i', trim($authorization), $matches)) {
        return null;
    }

    return $matches[1];
}

var_dump(bearerToken('Bearer access_123'));
var_dump(bearerToken('Token access_123'));

// Prints:
// string(10) "access_123"
// NULL

Bearer means possession is enough. If someone steals the token, they can use it until it expires or is revoked.

OAuth access tokens

OAuth is usually the right fit when a user authorises one application to access another service. It supports scopes, expiry, refresh, revocation, and consent screens.

Use OAuth when:

  • A third-party app acts on behalf of a user.
  • Access should be limited by scopes.
  • Users must be able to revoke access.
  • The provider already supports OAuth.

OAuth is more complex than an API key, but it solves user delegation in a standard way.

Signed requests

Signed requests use a secret to calculate a signature over the request method, path, timestamp, and body. They are useful when the receiver needs to know that the request was not changed in transit and is not an old replay.

PHP example
<?php

declare(strict_types=1);

function requestSignature(string $method, string $path, string $timestamp, string $body, string $secret): string
{
    $message = strtoupper($method) . "\n" . $path . "\n" . $timestamp . "\n" . $body;

    return hash_hmac('sha256', $message, $secret);
}

echo requestSignature('POST', '/v1/orders', '1779969900', '{"id":123}', 'secret') . PHP_EOL;

// Output is a sha256 HMAC signature.

Webhook providers often use this pattern.

Session cookies

Browser applications often authenticate with secure session cookies. That is normal for a PHP web app, but it brings browser-specific concerns such as CSRF protection, SameSite, HttpOnly, and Secure cookie flags.

For public JSON APIs used by non-browser clients, bearer tokens or API keys are usually clearer than session cookies.

Mutual TLS

Mutual TLS, often shortened to mTLS, authenticates clients with certificates. It is common in high-trust enterprise, banking, infrastructure, and service-to-service systems. It is powerful but operationally heavier because certificates must be issued, rotated, and revoked.

Choosing a pattern

Use the simplest pattern that fits the risk:

  • Internal script calling an internal API: API key or service token may be enough.
  • Third-party application acting for a user: OAuth.
  • Webhook receiver: signed requests with timestamp and idempotency.
  • Browser-backed web app: session cookies plus CSRF protection.
  • Highly controlled service-to-service traffic: mTLS or signed requests.

Whatever pattern you choose, document how credentials are created, stored, rotated, revoked, and logged.

What to check

Before moving on, make sure you can:

  • Compare API keys, bearer tokens, OAuth, signed requests, sessions, and mTLS.
  • Explain why authentication and authorisation are separate.
  • Avoid secrets in URLs and logs.
  • Choose a reasonable pattern for common PHP API scenarios.
  • Describe how credential rotation and revocation affect the design.

Practice

Practice: Choose An Auth Pattern

Write a small PHP function that recommends an API authentication pattern for a scenario.

Requirements

  • Accept scenario flags such as user_delegation, browser_client, webhook, and high_trust_service.
  • Recommend OAuth for user delegation.
  • Recommend signed requests for webhooks.
  • Recommend session cookies for browser-backed app routes.
  • Recommend API keys or service tokens for simple server-to-server access.
  • Return a short reason with each recommendation.
Show solution

This solution is deliberately a decision helper. Real architecture needs more context, but the branches reflect common API choices.

PHP example
<?php

declare(strict_types=1);

function recommendAuthPattern(array $scenario): array
{
    if (($scenario['webhook'] ?? false) === true) {
        return [
            'pattern' => 'signed request',
            'reason' => 'The receiver must verify the sender and protect against body tampering and replay.',
        ];
    }

    if (($scenario['user_delegation'] ?? false) === true) {
        return [
            'pattern' => 'OAuth',
            'reason' => 'A user is granting limited access to another application.',
        ];
    }

    if (($scenario['browser_client'] ?? false) === true) {
        return [
            'pattern' => 'secure session cookie',
            'reason' => 'The client is a browser-backed web app, so cookie security and CSRF protection matter.',
        ];
    }

    if (($scenario['high_trust_service'] ?? false) === true) {
        return [
            'pattern' => 'mTLS or signed service token',
            'reason' => 'The service boundary needs stronger operational control than a simple shared key.',
        ];
    }

    return [
        'pattern' => 'API key or service token',
        'reason' => 'A simple server-to-server integration can use a revocable secret when stored and logged safely.',
    ];
}

$examples = [
    recommendAuthPattern(['webhook' => true]),
    recommendAuthPattern(['user_delegation' => true]),
    recommendAuthPattern(['browser_client' => true]),
    recommendAuthPattern([]),
];

foreach ($examples as $result) {
    echo $result['pattern'] . ': ' . $result['reason'] . PHP_EOL;
}

// Prints:
// signed request: The receiver must verify the sender and protect against body tampering and replay.
// OAuth: A user is granting limited access to another application.
// secure session cookie: The client is a browser-backed web app, so cookie security and CSRF protection matter.
// API key or service token: A simple server-to-server integration can use a revocable secret when stored and logged safely.

The recommendation is only the start. A professional design also explains storage, rotation, revocation, scopes, and what must never be logged.