Blog Security · Backend

Securing Laravel APIs: The 2025
Security Checklist for Enterprise Apps

👨‍🔧Nuwan Bandara
· May 12, 2025 · 13 min read
Securing Laravel APIs — the 2025 security checklist for enterprise applications

API security is not optional. A single misconfigured endpoint can expose your entire user database, allow an attacker to impersonate any user, or enable denial-of-service attacks that take your business offline. We conduct security audits on Laravel APIs as part of every enterprise project handover. Here is the complete 10-point checklist we run through every time.

1. Authentication: Sanctum vs Passport

Use Laravel Sanctum for SPA authentication and simple mobile app token auth. Sanctum is lightweight, actively maintained, and sufficient for the vast majority of applications. Use Laravel Passport only if you need a full OAuth2 server — i.e., you are issuing tokens to third-party clients via authorisation code flow.

Common mistake: storing Sanctum tokens in localStorage. Always store them in secure, HttpOnly cookies (for SPAs) or in device-level secure storage (for mobile apps). localStorage is accessible from JavaScript and is vulnerable to XSS attacks.

2. Authorization: Always Use Policies

Authentication answers "who are you?" — authorization answers "what are you allowed to do?" They are different problems. Every API endpoint that accesses a resource must verify that the authenticated user is authorised to access that specific resource.

// WRONG: Only checks authentication, not authorization
public function show(Invoice $invoice) {
    return $invoice; // Any logged-in user can see any invoice!
}

// RIGHT: Uses a Policy to check ownership
public function show(Invoice $invoice) {
    $this->authorize('view', $invoice);
    return $invoice;
}

The missing authorization check (IDOR — Insecure Direct Object Reference) is the most common API vulnerability we find in audits. It's in the OWASP API Top 10 as the #1 API security risk.

3. Rate Limiting Every Endpoint

Rate limiting protects against brute-force attacks, credential stuffing, and scraping. In Laravel, apply rate limiting with named limiters in RouteServiceProvider and use the throttle middleware on your API routes. Apply stricter limits to sensitive endpoints — authentication routes should be significantly more restricted than read-only data endpoints.

RateLimiter::for('auth', function (Request $request) {
    return Limit::perMinute(5)->by($request->ip());
});

RateLimiter::for('api', function (Request $request) {
    return $request->user()
        ? Limit::perMinute(120)->by($request->user()->id)
        : Limit::perMinute(30)->by($request->ip());
});

4. Input Validation with Form Requests

Never trust user input. Use Laravel Form Request classes for all API input validation. Validate at the boundaries — before any business logic executes. Specify allowed fields explicitly (use $request->validated() not $request->all()) to prevent mass assignment vulnerabilities.

5. SQL Injection Prevention

Eloquent's query builder uses PDO parameterized queries by default, which prevents SQL injection as long as you use it correctly. The danger is raw queries:

// VULNERABLE to SQL injection
DB::select("SELECT * FROM users WHERE name = '{$name}'");

// SAFE: Use parameterised bindings
DB::select('SELECT * FROM users WHERE name = ?', [$name]);

// Even better: Use Eloquent
User::where('name', $name)->get();

6. CORS Configuration

Never set allowed_origins: ['*'] in production. Specify the exact domains of your frontend application. In config/cors.php, set allowed_origins to your exact frontend URLs. If you need to support multiple environments (staging, production), manage this through environment variables.

7. JWT Hardening

If using JWTs, enforce these settings: sign with RS256 (asymmetric), not HS256; set short expiry times (15 minutes for access tokens); implement refresh token rotation; store refresh tokens server-side for revocation capability; transmit tokens via HttpOnly cookies, not request headers (prevents XSS theft). Never log JWT tokens — they are equivalent to passwords.

8. Security Headers

Set these headers on every API response via middleware:

$response->headers->set('Strict-Transport-Security',
  'max-age=31536000; includeSubDomains; preload');
$response->headers->set('X-Content-Type-Options', 'nosniff');
$response->headers->set('X-Frame-Options', 'DENY');
$response->headers->set('X-XSS-Protection', '1; mode=block');
$response->headers->set('Referrer-Policy',
  'strict-origin-when-cross-origin');
$response->headers->remove('X-Powered-By'); // hide PHP version
$response->headers->remove('Server');       // hide server info

9. Sensitive Data Protection

Encrypt sensitive data at rest using Laravel's built-in encryption (AES-256-CBC via the Encrypted cast). Hash passwords with Bcrypt — never store them in plain text or use MD5/SHA1. Use $hidden arrays on Eloquent models to prevent sensitive fields being serialised into API responses. Log what users do but never log what their credentials are.

10. Dependency Security

Your application is only as secure as its dependencies. Run composer audit as part of your CI pipeline — it checks all dependencies against the PHP Security Advisories database. Automate this with a GitHub Actions step that fails the build if any high-severity vulnerabilities are found. Keep Laravel itself and all packages updated, especially security releases. Subscribe to Laravel security announcements via the official blog.

Want a Free Security Audit of Your Laravel API?

We run this 10-point security checklist on every client project. Let us audit your API and give you a detailed vulnerability report.

Request a Security Audit →

Related Articles

Ready to Build Something
Extraordinary?

The same expertise behind these articles goes into every project we build.