Secure API Design: Hardening Laravel Against Web Vulnerabilities
Learn to secure your Laravel API by mastering CORS, implementing CSRF protection for SPAs, and managing sensitive headers to prevent common web attacks.
Previously in this course, we explored rate limiting API endpoints to protect our infrastructure from abuse. In this lesson, we shift our focus to the request lifecycle itself, ensuring that the communication between your client-side application and your Laravel API remains locked down.
Building a secure API isn't just about authentication; it’s about controlling how and from where your application is accessed.
Understanding CORS in a Modern API
Cross-Origin Resource Sharing (CORS) is a browser-level security feature. By default, browsers restrict cross-origin HTTP requests initiated from scripts. If your frontend lives on app.example.com and your API on api.example.com, the browser will block requests unless your API explicitly permits them.
Configuring CORS Correctly
In Laravel, CORS is handled via the config/cors.php file. A common pitfall is setting allowed_origins to ['*']. This effectively disables CORS protection, allowing any malicious site to make requests to your API on behalf of your users.
Instead, define your specific production domains:
PHP#6A9955">// config/cors.php 'allowed_origins' => ['https:#6A9955">//app.example.com'], 'allowed_headers' => ['Content-Type', 'X-Requested-With', 'Authorization', 'X-XSRF-TOKEN'], 'supports_credentials' => true,
If you're building a Single Page Application (SPA) using Laravel Sanctum, supports_credentials must be true to allow the browser to send cookies (like your session cookie) across origins.
Implementing CSRF Protection for SPAs
Cross-Site Request Forgery (CSRF) tricks a user into submitting a request to a web application where they are currently authenticated. While APIs using stateless tokens (like Bearer tokens) are immune to CSRF, many Laravel SPAs use session-based authentication for convenience.
If you are using Sanctum's SPA authentication, you must implement CSRF protection. Laravel handles this via the EnsureFrontendRequestsAreStateful middleware.
The CSRF Workflow
- GET Request: The client makes a request to
/sanctum/csrf-cookie. - Cookie Issuance: Laravel sets an
XSRF-TOKENcookie. - Client Header: The frontend reads this cookie and includes its value in the
X-XSRF-TOKENheader of subsequent state-changing requests (POST, PUT, DELETE). - Verification: Laravel’s
VerifyCsrfTokenmiddleware checks that the header matches the encrypted cookie.
If you fail to send the X-XSRF-TOKEN header on a POST request, Laravel will return a 419 Authentication Timeout error. This is your signal that the security layer is doing its job.
Handling Sensitive Data Headers
Beyond CORS and CSRF, you must control what information your API leaks. Sensitive data often finds its way into logs or response headers.
Stripping Unnecessary Headers
By default, some servers or frameworks add headers like X-Powered-By: PHP/8.x. This is "security through obscurity," but it reduces your attack surface. You can remove these in your AppServiceProvider or via your web server configuration (Nginx/Apache).
PHP#6A9955">// app/Providers/AppServiceProvider.php public function boot(): void { $this->app['events']->listen(\Illuminate\Routing\Events\ResponseSending::class, function ($event) { $event->response->headers->remove('X-Powered-By'); }); }
Security Headers
Ensure your API sends modern security headers. You can use a dedicated middleware to inject these into every response:
- Strict-Transport-Security (HSTS): Forces browser to use HTTPS.
- X-Content-Type-Options: Prevents MIME-sniffing.
- Referrer-Policy: Controls how much referrer information is passed.
Hands-on Exercise
Your task is to harden the project board API:
- Update
config/cors.phpto restrictallowed_originsto your specific local development domain (e.g.,http://localhost:3000). - Ensure
supports_credentialsis set totrue. - In your frontend client, implement a request interceptor (using Axios or Fetch) that reads the
XSRF-TOKENcookie and attaches it to theX-XSRF-TOKENheader.
Common Pitfalls
- Wildcard CORS: Using
['*']in production is a major security risk. Always whitelist specific domains. - Ignoring 419 Errors: A 419 error is not a bug; it means your CSRF token is missing or expired. Do not disable CSRF protection just to make the error go away.
- Insecure Cookies: Always ensure
SESSION_SECURE_COOKIEis set totruein your.envfile when running in production to ensure cookies are only transmitted over HTTPS.
Recap
Secure API design requires a multi-layered approach. We've ensured that only authorized origins can talk to our API via CORS, verified stateful requests using Sanctum's CSRF protection, and sanitized our response headers to limit information leakage. These steps, combined with API security: decoupling field-level authorization from controllers, provide a robust foundation for your project board.
Up next: We will dive into Event Sourcing Concepts to understand how to handle complex state changes in our application.
Work with me

Laravel REST API Development
Clean, secure, well-documented Laravel REST APIs — the backend engine for your app, mobile client, or SaaS. Built by an API specialist.

FilamentPHP Admin Panel & Dashboard Development
A powerful admin panel for your Laravel app — built with FilamentPHP so you can manage everything without touching the database.