The SignalWire PHP SDK provides a unified security configuration system with secure defaults for HTTPS, basic authentication, and security headers.
export SWML_SSL_ENABLED=true
export SWML_SSL_CERT_PATH=/path/to/cert.pem
export SWML_SSL_KEY_PATH=/path/to/key.pem
export SWML_DOMAIN=yourdomain.comBasic auth is enabled by default with auto-generated credentials:
export SWML_BASIC_AUTH_USER=myusername
export SWML_BASIC_AUTH_PASSWORD=mysecurepassword| Variable | Default | Description |
|---|---|---|
SWML_SSL_ENABLED |
false |
Enable HTTPS |
SWML_SSL_CERT_PATH |
- | Path to SSL certificate |
SWML_SSL_KEY_PATH |
- | Path to SSL private key |
SWML_DOMAIN |
- | Domain name for URL generation |
| Variable | Default | Description |
|---|---|---|
SWML_BASIC_AUTH_USER |
signalwire |
Basic auth username |
SWML_BASIC_AUTH_PASSWORD |
auto-generated | Basic auth password (32-char token) |
| Variable | Default | Description |
|---|---|---|
SWML_CORS_ORIGINS |
* |
CORS allowed origins (comma-separated) |
SWML_ALLOWED_HOSTS |
* |
Allowed Host header values (comma-separated) |
SWML_RATE_LIMIT |
60 |
Requests per minute per IP |
SWML_MAX_REQUEST_SIZE |
10485760 |
Max request body size in bytes (10 MiB) |
SWML_REQUEST_TIMEOUT |
30 |
Per-request timeout in seconds |
SWML_USE_HSTS |
true |
Emit the HSTS response header when serving over TLS |
SWML_HSTS_MAX_AGE |
31536000 |
HSTS max-age in seconds (1 year) |
SWML_SSL_VERIFY_MODE |
CERT_REQUIRED |
TLS peer-certificate verification mode |
These knobs relax a default-secure behavior — set them only when you understand the exposure.
| Variable | Default | Description |
|---|---|---|
SWML_ALLOW_PRIVATE_URLS |
false |
Allow SDK fetches to private/loopback IPs (SSRF guard off) |
SWML_SKIP_SCHEMA_VALIDATION |
false |
Skip SWML schema validation (1/true/yes to disable) |
use SignalWire\Agent\AgentBase;
$agent = new AgentBase(name: 'secure-agent', route: '/agent');
[$user, $pass] = $agent->getBasicAuthCredentials();
echo "Auth: {$user}:{$pass}\n";When SWML_BASIC_AUTH_PASSWORD is not set, a random 32-character token is generated at startup and printed to the console.
SWAIG function calls from SignalWire include authentication headers. The SDK validates these automatically.
Tools can require metadata tokens for scoped data access:
$agent->defineTool(
name: 'get_patient_info',
description: 'Get patient medical information',
parameters: [
'type' => 'object',
'properties' => [
'patient_id' => ['type' => 'string', 'description' => 'Patient ID'],
],
],
handler: function (array $args, array $rawData): FunctionResult {
// $rawData contains meta_data_token and meta_data
$token = $rawData['meta_data_token'] ?? null;
if (!$token) {
return new FunctionResult('Access denied: no metadata token.');
}
return new FunctionResult("Patient info retrieved.");
},
);For production, use a reverse proxy (nginx, Caddy) for TLS termination:
server {
listen 443 ssl;
server_name agent.example.com;
ssl_certificate /etc/letsencrypt/live/agent.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/agent.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}# Production environment
export SWML_BASIC_AUTH_USER=prod_user
export SWML_BASIC_AUTH_PASSWORD=$(openssl rand -hex 16)
export SWML_SSL_ENABLED=true
export SWML_DOMAIN=agent.example.comThe REST client authenticates with project credentials:
use SignalWire\REST\RestClient;
$client = new RestClient(
getenv('SIGNALWIRE_PROJECT_ID'),
getenv('SIGNALWIRE_API_TOKEN'),
getenv('SIGNALWIRE_SPACE'),
);Credentials are sent as HTTP Basic Auth on every request. Always use environment variables -- never hardcode credentials.
The RELAY client authenticates over WebSocket:
use SignalWire\Relay\Client;
$client = new Client([
'project' => getenv('SIGNALWIRE_PROJECT_ID'),
'token' => getenv('SIGNALWIRE_API_TOKEN'),
'host' => getenv('SIGNALWIRE_SPACE') ?: 'relay.signalwire.com',
]);The WebSocket connection uses TLS by default. Authentication runs as part of connect().
- Never hardcode credentials in source files
- Use environment variables for all secrets
- Rotate API tokens regularly
- Enable HTTPS in production (directly or via reverse proxy)
- Use auto-generated passwords for basic auth when possible
- Keep the basic auth password in a secrets manager for multi-instance deployments