Security
Automation Hub is built with security-first principles. This page documents all security mechanisms, from authentication and encryption to network protections and audit logging.
Authentication
Automation Hub supports two authentication methods:
| Method | Use Case | Details |
|---|---|---|
| Session-based (Web) | Browser UI access | HTTP-only cookies, database-backed sessions, SameSite=lax |
| API Keys | REST API access | SHA-256 hashed storage, never stored in plain text, per-key rate limits |
API Key Security
API keys are hashed with SHA-256 before storage. The plain-text key is shown only once at creation time. If lost, the key must be revoked and a new one generated.
Two-Factor Authentication (2FA)
Users can enable TOTP-based two-factor authentication for an additional layer of security.
- Protocol: Time-based One-Time Password (TOTP) — compatible with Google Authenticator, Authy, 1Password, etc.
- Recovery Codes: 8 single-use recovery codes generated at setup, stored encrypted in the database
- Encrypted Storage: The TOTP secret is stored using Laravel's encrypted cast — encrypted at rest with AES-256
Password Policy
- Hashing: Passwords are hashed with bcrypt (default) or argon2id (configurable)
- Rounds: Configurable bcrypt rounds (default: 12) via
config/hashing.php - Minimum Length: 8 characters minimum (enforced server-side)
- Generic Error Messages: Login failures return generic messages to prevent user enumeration
Rate Limiting
| Endpoint | Limit | Window |
|---|---|---|
Login (/login) | 5 attempts | Per minute, per IP |
Register (/register) | 5 requests | Per minute, per IP |
| Forgot Password | 5 requests | Per minute, per IP |
| Reset Password | 5 requests | Per minute, per IP |
| API Endpoints | Configurable | Per-key + per-organization limits |
When rate limited, the API returns a 429 Too Many Requests response with a Retry-After header indicating seconds to wait.
CSRF Protection
All web routes are protected by CSRF tokens verified on every state-changing request (POST, PUT, PATCH, DELETE). The only exception is the installation wizard, which operates before sessions are fully configured.
CORS Policy
Cross-Origin Resource Sharing is restricted to the APP_URL origin only. API requests from other origins are rejected. This prevents unauthorized cross-origin access to the API.
SSRF Protection
The HTTP Request node and polling mechanisms include Server-Side Request Forgery (SSRF) protections. The following private IP ranges are blocked:
127.0.0.0/8 (localhost)
10.0.0.0/8 (private class A)
172.16.0.0/12 (private class B)
192.168.0.0/16 (private class C)
::1 (IPv6 localhost)
fc00::/7 (IPv6 private)
This prevents workflows from making requests to internal services, databases, or cloud metadata endpoints.
Input Validation
- Server-side validation on all endpoints using Laravel Form Requests
- Type coercion protection — strict type checking on API inputs
- Generic auth errors — login and password reset endpoints return the same message for valid and invalid emails, preventing user enumeration
- SQL injection protection — all queries use Eloquent ORM with parameterized queries
- XSS protection — React's JSX auto-escapes output; server responses use appropriate Content-Type headers
Encrypted Credentials
All sensitive module credentials (API keys for email providers, WhatsApp tokens, AI service keys, courier API keys) are stored using Laravel's encrypted cast. This means:
- Values are encrypted with AES-256-CBC before database storage
- Decryption happens automatically when accessed in PHP
- Even if the database is compromised, credentials remain encrypted
- The encryption key is derived from your
APP_KEYenvironment variable
Audit Logging
All administrative actions are logged to the audit trail with:
- User ID — Who performed the action
- IP Address — Where the request originated
- Action — What was performed (create, update, delete, login, logout, etc.)
- Entity — The affected model and ID
- Old/New Values — A JSON diff of what changed (for updates)
- Timestamp — When the action occurred
Audit logs are queryable via the admin UI and the GET /api/v1/audit-logs endpoint (requires audit.view permission).
Organization Isolation
Multi-tenant data isolation is enforced at the database query level using an OrganizationScope global scope applied to all tenant models. This ensures:
- Users can only access data belonging to their current organization
- Queries are automatically scoped — no manual filtering required
- Cross-tenant data access is impossible even if IDs are guessed
- API keys are scoped to a single organization
HMAC Webhook Verification
Outbound webhooks include an HMAC-SHA256 signature for verification:
- Each webhook has a unique secret generated at creation
- The request body is signed with
HMAC-SHA256(secret, body) - The signature is sent in the
X-Webhook-Signatureheader - Recipients should verify the signature before processing the payload
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$payload = file_get_contents('php://input');
$expected = hash_hmac('sha256', $payload, $webhookSecret);
if (!hash_equals($expected, $signature)) {
http_response_code(401);
exit('Invalid signature');
}
Session Security
| Setting | Value | Purpose |
|---|---|---|
| Cookie Flag | HttpOnly | Prevents JavaScript access to session cookies |
| SameSite | lax | Prevents CSRF via cross-origin requests |
| Secure | Auto (HTTPS) | Cookies only sent over HTTPS in production |
| Driver | database | Sessions stored in DB for scalability and auditability |
| Lifetime | 120 minutes | Configurable session expiration |
Captcha Protection
Automation Hub includes built-in captcha protection for all public-facing authentication forms to prevent spam, bot registrations, and brute-force attacks. Two providers are supported:
| Provider | Type | Best For |
|---|---|---|
| Cloudflare Turnstile | Visible widget (privacy-friendly) | Recommended — free, no tracking, GDPR-compliant |
| Google reCAPTCHA v3 | Invisible (score-based) | Alternative — invisible, risk scoring (min score 0.5) |
Protected Forms
- Login (
/login) — prevents credential stuffing - Registration (
/register) — prevents bot signups - Forgot Password (
/forgot-password) — prevents email enumeration abuse
Configuration
Captcha is disabled by default for backward compatibility. To enable, add these variables to your .env file:
CAPTCHA_ENABLED=true
CAPTCHA_PROVIDER=turnstile
TURNSTILE_SITE_KEY=0x4AAAAAAA...your_site_key
TURNSTILE_SECRET_KEY=0x4AAAAAAA...your_secret_key
CAPTCHA_ENABLED=true
CAPTCHA_PROVIDER=recaptcha
RECAPTCHA_SITE_KEY=6Lc...your_site_key
RECAPTCHA_SECRET_KEY=6Lc...your_secret_key
How It Works
-
1
Frontend Widget
When captcha is enabled, the
CaptchaWidgetReact component automatically loads the appropriate provider script and renders the challenge (visible for Turnstile, invisible for reCAPTCHA v3). -
2
Token Generation
Upon successful verification, the provider returns a one-time token that is included in the form submission as
captcha_token. -
3
Server-Side Verification
The
ValidCaptcharule sends the token to the provider's verification API (Cloudflare or Google) and checks the response. If verification fails, the form submission is rejected with a validation error.
Getting Captcha Keys
Cloudflare Turnstile: Go to Cloudflare Dashboard → Turnstile, add a site, and copy the site key and secret key. It's completely free with no request limits.
Google reCAPTCHA v3: Go to reCAPTCHA Admin, register a new site with reCAPTCHA v3, and copy the keys.
Security Best Practices
For production deployments: always use HTTPS, keep APP_DEBUG=false, rotate your APP_KEY periodically, enable 2FA for all admin users, enable captcha protection, and regularly review the audit log for suspicious activity.