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
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
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
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, andhigh_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
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.