Skip to content

Security Considerations

Authentication & Session

  • Laravel Fortify provides the authentication backend (login, registration, password reset, 2FA); see config/fortify.php and routes/auth.php.
  • Laravel Sanctum guards SPA sessions & API tokens. Ensure SANCTUM_STATEFUL_DOMAINS is configured for cookie-based sessions in multi-domain setups.

Authorization

  • Spatie Permission defines roles & permissions; keep them granular.
  • Policies enforce model-level constraints; validate user context (isShop() / isClient()).
  • EnsureUserTypeShop / EnsureUserTypeClient gate whole route groups. Note they redirect (302) rather than returning 403.
  • Laravel Actions run authorize() before asController() — a failure there is a 403.

Data Validation

  • Always validate incoming data via Form Requests.
  • Use DTOs (Spatie Data) internally to prevent unvalidated arrays propagating.

Sensitive Configuration

Store secrets ONLY in .env:

  • APP_KEY, DB_PASSWORD, SENTRY_DSN, TWILIO_AUTH_TOKEN, webhook signing secrets. Never commit .env.

Logging Hygiene

  • Avoid logging PII (personally identifiable information) or credentials.
  • Activity logs should capture actions (who, what, when) without sensitive payloads.

Error Reporting

  • Sentry captures exceptions; configure data scrubbing rules if necessary.
  • Avoid exposing stack traces in production responses (exception handling configured by Laravel).

WebSockets Security

  • Private & presence channels must implement authorization callbacks (in routes/channels.php).
  • Reuse permission checks; do not duplicate logic.
  • Model broadcasting is intentionally per-instance (models.{tableAlias}.{id}). Do not introduce a class-wide channel: it would authorize via viewAny(), which is not shop-scoped, and leak newly created records across tenants.

Webhook Security

  • Validate signatures with spatie/laravel-webhook-client; secrets & profiles in config/webhook-client.php.
  • bootstrap/app.php exempts webhook/* from CSRF — signature validation is therefore the only thing standing between the internet and those handlers. Never add an unsigned route under that prefix.
  • Reject unsigned or expired requests early.
  • Rate limit endpoints if publicly accessible.

File & Media Handling

  • Use Media Library conversions to sanitize uploads.
  • Validate file types & sizes before attaching.
  • Store sensitive documents on private disks (e.g., S3 with restricted ACL).

Dependencies & Updates

  • Monitor Laravel, Fortify, Sanctum, Horizon, Reverb, and Sentry for security patches.
  • Run ./vendor/bin/sail composer audit for known vulnerabilities.
  • The Pulse dashboard carries cards for outdated (pulse-outdated) and vulnerable (hungthai1401/vulnerable) Composer dependencies — check them periodically.

SQL & Query Safety

  • Use Eloquent or parameterized queries; avoid raw concatenated SQL.
  • Leverage query scopes for consistent tenancy constraints.

Rate Limiting & Throttling

  • Apply throttle middleware to authentication & webhook endpoints.
  • Consider per-user or per-role limits for resource-intensive operations (file uploads, PDF generation).

Input Sanitization

  • Escape dynamic output in Blade (if used) or rely on Vue binding safety.
  • Strip or encode HTML in user-submitted rich text if not required (XSS mitigation).

Password & Credential Management

  • Rely on Laravel's hashing configuration (bcrypt/argon2id) for user passwords.
  • Enforce strong password rules in Form Requests.

Transport Security

  • Serve over HTTPS; ensure correct APP_URL configured.
  • Use secure cookies in production (SESSION_SECURE_COOKIE=true).

Session & CSRF

  • CSRF protection enabled on web routes by default.
  • For APIs consumed by SPAs, ensure Sanctum token / session flow is correctly set.

Backups & Disaster Recovery (Recommendations)

  • Schedule DB dumps (encrypted) stored off-site.
  • Maintain media backup lifecycle (versioning & retention).

Monitoring & Alerts

  • Configure Sentry alerts for high error rates.
  • Consider Slack/Email notifications for Horizon job failures or queue backlog thresholds.

Least Privilege Principle

  • Limit roles to necessary permissions; avoid catch-all roles.
  • Restrict access to administrative dashboards (Horizon, Pulse) via gate checks.

Example Channel Authorization

php
Broadcast::channel('models.cars.{id}', function (User $user, int $id) {
    return $user->isShop() && Car::query()
        ->whereKey($id)
        ->where('shop_id', $user->currentShop->id)
        ->exists();
});

Every channel callback must re-assert the tenant, not just authentication.

Consult troubleshooting.md for resolving auth-related issues.